• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 "core/components/custom_paint/rosen_render_offscreen_canvas.h"
17 
18 #include <cmath>
19 #include <sstream>
20 
21 #include "txt/paragraph_builder.h"
22 #include "txt/paragraph_style.h"
23 #ifndef USE_ROSEN_DRAWING
24 #include "include/core/SkBlendMode.h"
25 #include "include/core/SkColor.h"
26 #include "include/core/SkMaskFilter.h"
27 #include "include/core/SkPoint.h"
28 #ifndef NEW_SKIA
29 #include "include/effects/SkBlurImageFilter.h"
30 #else
31 #include "include/core/SkColorFilter.h"
32 #include "include/effects/SkImageFilters.h"
33 #endif
34 #endif
35 #include "include/effects/SkDashPathEffect.h"
36 #include "include/effects/SkGradientShader.h"
37 #include "include/encode/SkJpegEncoder.h"
38 #include "include/encode/SkPngEncoder.h"
39 #include "include/encode/SkWebpEncoder.h"
40 #include "include/utils/SkBase64.h"
41 #include "include/utils/SkParsePath.h"
42 
43 #include "base/i18n/localization.h"
44 #include "base/image/pixel_map.h"
45 #include "base/log/log.h"
46 #include "base/utils/string_utils.h"
47 #ifndef NEW_SKIA
48 #include "core/components/common/painter/flutter_decoration_painter.h"
49 #else
50 #include "core/components/common/painter/rosen_decoration_painter.h"
51 #endif
52 #include "core/components/font/constants_converter.h"
53 #ifndef NEW_SKIA
54 #include "core/components/font/flutter_font_collection.h"
55 #else
56 #include "core/components/font/rosen_font_collection.h"
57 #endif
58 #ifdef USE_ROSEN_DRAWING
59 #include "core/components_ng/render/drawing.h"
60 #endif
61 #include "core/image/image_provider.h"
62 
63 namespace OHOS::Ace {
64 namespace {
65 constexpr double HANGING_PERCENT = 0.8;
66 #ifndef USE_ROSEN_DRAWING
67 template<typename T, typename N>
ConvertEnumToSkEnum(T key,const LinearEnumMapNode<T,N> * map,size_t length,N defaultValue)68     N ConvertEnumToSkEnum(T key, const LinearEnumMapNode<T, N>* map, size_t length, N defaultValue)
69     {
70         int64_t index = BinarySearchFindIndex(map, length, key);
71         return index != -1 ? map[index].value : defaultValue;
72     }
73 #else
74 template<typename T, typename N>
ConvertEnumToDrawingEnum(T key,const LinearEnumMapNode<T,N> * map,size_t length,N defaultValue)75     N ConvertEnumToDrawingEnum(T key, const LinearEnumMapNode<T, N>* map, size_t length, N defaultValue)
76     {
77         int64_t index = BinarySearchFindIndex(map, length, key);
78         return index != -1 ? map[index].value : defaultValue;
79     }
80 #endif
81 
82 constexpr double DEFAULT_QUALITY = 0.92;
83 constexpr int32_t MAX_LENGTH = 2048 * 2048;
84 const std::string UNSUPPORTED = "data:image/png";
85 const std::string URL_PREFIX = "data:";
86 const std::string URL_SYMBOL = ";base64,";
87 const std::string IMAGE_PNG = "image/png";
88 const std::string IMAGE_JPEG = "image/jpeg";
89 const std::string IMAGE_WEBP = "image/webp";
90 constexpr double HALF_CIRCLE_ANGLE = 180.0;
91 constexpr double FULL_CIRCLE_ANGLE = 360.0;
92 
93 // If args is empty or invalid format, use default: image/png
GetMimeType(const std::string & args)94 std::string GetMimeType(const std::string& args)
95 {
96     std::string type = args;
97     for (size_t i = 0; i < type.size(); ++i) {
98         type[i] = static_cast<uint8_t>(tolower(type[i]));
99     }
100     return type;
101 }
102 
103 // Quality need between 0.0 and 1.0 for MimeType jpeg and webp
GetQuality(const std::string & args,const double quality)104 double GetQuality(const std::string& args, const double quality)
105 {
106     std::string type = args;
107     auto mimeType = GetMimeType(type);
108     if (mimeType != IMAGE_JPEG && mimeType != IMAGE_WEBP) {
109         return DEFAULT_QUALITY;
110     }
111     if (quality < 0.0 || quality > 1.0) {
112         return DEFAULT_QUALITY;
113     }
114     return quality;
115 }
116 
117 #ifndef USE_ROSEN_DRAWING
118 const LinearEnumMapNode<CompositeOperation, SkBlendMode> SK_BLEND_MODE_TABLE[] = {
119     { CompositeOperation::SOURCE_OVER, SkBlendMode::kSrcOver },
120     { CompositeOperation::SOURCE_ATOP, SkBlendMode::kSrcATop },
121     { CompositeOperation::SOURCE_IN, SkBlendMode::kSrcIn },
122     { CompositeOperation::SOURCE_OUT, SkBlendMode::kSrcOut },
123     { CompositeOperation::DESTINATION_OVER, SkBlendMode::kDstOver },
124     { CompositeOperation::DESTINATION_ATOP, SkBlendMode::kDstATop },
125     { CompositeOperation::DESTINATION_IN, SkBlendMode::kDstIn },
126     { CompositeOperation::DESTINATION_OUT, SkBlendMode::kDstOut },
127     { CompositeOperation::LIGHTER, SkBlendMode::kLighten },
128     { CompositeOperation::COPY, SkBlendMode::kSrc },
129     { CompositeOperation::XOR, SkBlendMode::kXor },
130 };
131 constexpr size_t BLEND_MODE_SIZE = ArraySize(SK_BLEND_MODE_TABLE);
132 #else
133 const LinearEnumMapNode<CompositeOperation, RSBlendMode> DRAWING_BLEND_MODE_TABLE[] = {
134     { CompositeOperation::SOURCE_OVER, RSBlendMode::SRC_OVER },
135     { CompositeOperation::SOURCE_ATOP, RSBlendMode::SRC_ATOP },
136     { CompositeOperation::SOURCE_IN, RSBlendMode::SRC_IN },
137     { CompositeOperation::SOURCE_OUT, RSBlendMode::SRC_OUT },
138     { CompositeOperation::DESTINATION_OVER, RSBlendMode::DST_OVER },
139     { CompositeOperation::DESTINATION_ATOP, RSBlendMode::DST_ATOP },
140     { CompositeOperation::DESTINATION_IN, RSBlendMode::DST_IN },
141     { CompositeOperation::DESTINATION_OUT, RSBlendMode::DST_OUT },
142     { CompositeOperation::LIGHTER, RSBlendMode::LIGHTEN },
143     { CompositeOperation::COPY, RSBlendMode::SRC },
144     { CompositeOperation::XOR, RSBlendMode::XOR },
145 };
146 constexpr size_t BLEND_MODE_SIZE = ArraySize(DRAWING_BLEND_MODE_TABLE);
147 #endif
148 } // namespace
149 
RosenRenderOffscreenCanvas(const WeakPtr<PipelineBase> & context,int32_t width,int32_t height)150 RosenRenderOffscreenCanvas::RosenRenderOffscreenCanvas(const WeakPtr<PipelineBase>& context,
151     int32_t width, int32_t height)
152 {
153     pipelineContext_ = context;
154     width_ = width;
155     height_ = height;
156 #ifndef USE_ROSEN_DRAWING
157     auto imageInfo = SkImageInfo::Make(width, height, SkColorType::kRGBA_8888_SkColorType,
158         SkAlphaType::kOpaque_SkAlphaType);
159     skBitmap_.allocPixels(imageInfo);
160     cacheBitmap_.allocPixels(imageInfo);
161     skBitmap_.eraseColor(SK_ColorTRANSPARENT);
162     cacheBitmap_.eraseColor(SK_ColorTRANSPARENT);
163     skCanvas_ = std::make_unique<SkCanvas>(skBitmap_);
164     cacheCanvas_ = std::make_unique<SkCanvas>(cacheBitmap_);
165 #else
166     RSBitmapFormat format { RSColorType::COLORTYPE_RGBA_8888,
167         RSAlphaType::ALPHATYPE_OPAQUE };
168     bitmap_.Build(width, height, format);
169     cacheBitmap_.Build(width, height, format);
170     bitmap_.ClearWithColor(RSColor::COLOR_TRANSPARENT);
171     cacheBitmap_.ClearWithColor(RSColor::COLOR_TRANSPARENT);
172     canvas_->Bind(bitmap_);
173     cacheCanvas_->Bind(cacheBitmap_);
174 #endif
175     InitFilterFunc();
176     InitImageCallbacks();
177 }
AddRect(const Rect & rect)178 void RosenRenderOffscreenCanvas::AddRect(const Rect& rect)
179 {
180 #ifndef USE_ROSEN_DRAWING
181     SkRect skRect = SkRect::MakeLTRB(rect.Left(), rect.Top(),
182         rect.Right(), rect.Bottom());
183     skPath_.addRect(skRect);
184 #else
185     RSRect drawingRect(rect.Left(), rect.Top(), rect.Right(), rect.Bottom());
186     path_.AddRect(drawingRect);
187 #endif
188 }
189 
SetFillRuleForPath(const CanvasFillRule & rule)190 void RosenRenderOffscreenCanvas::SetFillRuleForPath(const CanvasFillRule& rule)
191 {
192     if (rule == CanvasFillRule::NONZERO) {
193 #ifndef USE_ROSEN_DRAWING
194 #ifndef NEW_SKIA
195         skPath_.setFillType(SkPath::FillType::kWinding_FillType);
196 #else
197         skPath_.setFillType(SkPathFillType::kWinding);
198 #endif
199     } else if (rule == CanvasFillRule::EVENODD) {
200 #ifndef NEW_SKIA
201         skPath_.setFillType(SkPath::FillType::kEvenOdd_FillType);
202 #else
203         skPath_.setFillType(SkPathFillType::kEvenOdd);
204 #endif
205 #else
206     if (rule == CanvasFillRule::NONZERO) {
207         path_.SetFillStyle(RSPathFillType::WINDING);
208     } else if (rule == CanvasFillRule::EVENODD) {
209         path_.SetFillStyle(RSPathFillType::EVENTODD);
210     }
211 #endif
212     }
213 }
214 
SetFillRuleForPath2D(const CanvasFillRule & rule)215 void RosenRenderOffscreenCanvas::SetFillRuleForPath2D(const CanvasFillRule& rule)
216 {
217 #ifndef USE_ROSEN_DRAWING
218     if (rule == CanvasFillRule::NONZERO) {
219 #ifndef NEW_SKIA
220         skPath2d_.setFillType(SkPath::FillType::kWinding_FillType);
221 #else
222         skPath2d_.setFillType(SkPathFillType::kWinding);
223 #endif
224     } else if (rule == CanvasFillRule::EVENODD) {
225 #ifndef NEW_SKIA
226         skPath2d_.setFillType(SkPath::FillType::kEvenOdd_FillType);
227 #else
228         skPath2d_.setFillType(SkPathFillType::kEvenOdd);
229 #endif
230     }
231 #else
232     if (rule == CanvasFillRule::NONZERO) {
233         path2d_.SetFillStyle(RSPathFillType::WINDING);
234     } else if (rule == CanvasFillRule::EVENODD) {
235         path2d_.SetFillStyle(RSPathFillType::EVENTODD);
236     }
237 #endif
238 }
239 
ParsePath2D(const RefPtr<CanvasPath2D> & path)240 void RosenRenderOffscreenCanvas::ParsePath2D(const RefPtr<CanvasPath2D>& path)
241 {
242     for (const auto& [cmd, args] : path->GetCaches()) {
243         switch (cmd) {
244             case PathCmd::CMDS: {
245                 Path2DAddPath(args);
246                 break;
247             }
248             case PathCmd::TRANSFORM: {
249                 Path2DSetTransform(args);
250                 break;
251             }
252             case PathCmd::MOVE_TO: {
253                 Path2DMoveTo(args);
254                 break;
255             }
256             case PathCmd::LINE_TO: {
257                 Path2DLineTo(args);
258                 break;
259             }
260             case PathCmd::ARC: {
261                 Path2DArc(args);
262                 break;
263             }
264             case PathCmd::ARC_TO: {
265                 Path2DArcTo(args);
266                 break;
267             }
268             case PathCmd::QUADRATIC_CURVE_TO: {
269                 Path2DQuadraticCurveTo(args);
270                 break;
271             }
272             case PathCmd::BEZIER_CURVE_TO: {
273                 Path2DBezierCurveTo(args);
274                 break;
275             }
276             case PathCmd::ELLIPSE: {
277                 Path2DEllipse(args);
278                 break;
279             }
280             case PathCmd::RECT: {
281                 Path2DRect(args);
282                 break;
283             }
284             case PathCmd::CLOSE_PATH: {
285                 Path2DClosePath(args);
286                 break;
287             }
288             default: {
289                 break;
290             }
291         }
292     }
293 }
294 
Fill()295 void RosenRenderOffscreenCanvas::Fill()
296 {
297 #ifndef USE_ROSEN_DRAWING
298     SkPaint paint;
299     paint.setAntiAlias(antiAlias_);
300     paint.setColor(fillState_.GetColor().GetValue());
301     paint.setStyle(SkPaint::Style::kFill_Style);
302     if (HasShadow()) {
303 #ifndef NEW_SKIA
304         FlutterDecorationPainter::PaintShadow(skPath_, shadow_, skCanvas_.get());
305 #else
306         RosenDecorationPainter::PaintShadow(skPath_, shadow_, skCanvas_.get());
307 #endif
308     }
309     if (fillState_.GetGradient().IsValid()) {
310         UpdatePaintShader(paint, fillState_.GetGradient());
311     }
312     if (fillState_.GetPattern().IsValid()) {
313         UpdatePaintShader(fillState_.GetPattern(), paint);
314     }
315     if (globalState_.HasGlobalAlpha()) {
316         paint.setAlphaf(globalState_.GetAlpha());
317     }
318     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
319         skCanvas_->drawPath(skPath_, paint);
320     } else {
321         InitCachePaint();
322         cacheCanvas_->drawPath(skPath_, paint);
323 #ifndef NEW_SKIA
324         skCanvas_->drawBitmap(cacheBitmap_, 0, 0, &cachePaint_);
325 #else
326         skCanvas_->drawImage(cacheBitmap_.asImage(), 0, 0, SkSamplingOptions(), &cachePaint_);
327 #endif
328         cacheBitmap_.eraseColor(0);
329     }
330 #else
331     RSBrush brush;
332     brush.SetAntiAlias(antiAlias_);
333     brush.SetColor(fillState_.GetColor().GetValue());
334     if (HasShadow()) {
335         RosenDecorationPainter::PaintShadow(path_, shadow_, canvas_.get());
336     }
337     if (fillState_.GetGradient().IsValid()) {
338         UpdatePaintShader(nullptr, &brush, fillState_.GetGradient());
339     }
340     if (fillState_.GetPattern().IsValid()) {
341         UpdatePaintShader(fillState_.GetPattern(), nullptr, &brush);
342     }
343     if (globalState_.HasGlobalAlpha()) {
344         brush.SetAlphaF(globalState_.GetAlpha());
345     }
346     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
347         canvas_->AttachBrush(brush);
348         canvas_->DrawPath(path_);
349         canvas_->DetachBrush();
350     } else {
351         InitCachePaint();
352         cacheCanvas_->AttachBrush(brush);
353         cacheCanvas_->DrawPath(path_);
354         cacheCanvas_->DetachBrush();
355         canvas_->AttachBrush(cacheBrush_);
356         canvas_->DrawBitmap(cacheBitmap_, 0, 0);
357         canvas_->DetachBrush();
358         cacheBitmap_.ClearWithColor(RSColor::COLOR_TRANSPARENT);
359     }
360 #endif
361 }
362 
Fill(const RefPtr<CanvasPath2D> & path)363 void RosenRenderOffscreenCanvas::Fill(const RefPtr<CanvasPath2D>& path)
364 {
365     if (path == nullptr) {
366         LOGE("Fill failed in offscreenCanvas, target path is null.");
367         return;
368     }
369     ParsePath2D(path);
370     Path2DFill();
371 #ifndef USE_ROSEN_DRAWING
372     skPath2d_.reset();
373 #else
374     path2d_.Reset();
375 #endif
376 }
377 
Clip()378 void RosenRenderOffscreenCanvas::Clip()
379 {
380 #ifndef USE_ROSEN_DRAWING
381     skCanvas_->clipPath(skPath_);
382 #else
383     canvas_->ClipPath(path_, RSClipOp::INTERSECT, false);
384 #endif
385 }
386 
Clip(const RefPtr<CanvasPath2D> & path)387 void RosenRenderOffscreenCanvas::Clip(const RefPtr<CanvasPath2D>& path)
388 {
389     if (path == nullptr) {
390         LOGE("Clip failed in offscreenCanvas, target path is null.");
391         return;
392     }
393     ParsePath2D(path);
394     Path2DClip();
395 #ifndef USE_ROSEN_DRAWING
396     skPath2d_.reset();
397 #else
398     path2d_.Reset();
399 #endif
400 }
401 
FillRect(Rect rect)402 void RosenRenderOffscreenCanvas::FillRect(Rect rect)
403 {
404 #ifndef USE_ROSEN_DRAWING
405     SkPaint paint;
406     paint.setAntiAlias(antiAlias_);
407     paint.setColor(fillState_.GetColor().GetValue());
408     paint.setStyle(SkPaint::Style::kFill_Style);
409     SkRect skRect = SkRect::MakeLTRB(rect.Left(), rect.Top(), rect.Right(), rect.Bottom());
410     if (HasShadow()) {
411         SkPath path;
412         path.addRect(skRect);
413 #ifndef NEW_SKIA
414         FlutterDecorationPainter::PaintShadow(path, shadow_, skCanvas_.get());
415 #else
416         RosenDecorationPainter::PaintShadow(path, shadow_, skCanvas_.get());
417 #endif
418     }
419     if (fillState_.GetGradient().IsValid()) {
420         UpdatePaintShader(paint, fillState_.GetGradient());
421     }
422     if (fillState_.GetPattern().IsValid()) {
423         UpdatePaintShader(fillState_.GetPattern(), paint);
424     }
425     if (globalState_.HasGlobalAlpha()) {
426         paint.setAlphaf(globalState_.GetAlpha()); // update the global alpha after setting the color
427     }
428     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
429         skCanvas_->drawRect(skRect, paint);
430     } else {
431         InitCachePaint();
432         cacheCanvas_->drawRect(skRect, paint);
433 #ifndef NEW_SKIA
434         skCanvas_->drawBitmap(cacheBitmap_, 0, 0, &cachePaint_);
435 #else
436         skCanvas_->drawImage(cacheBitmap_.asImage(), 0, 0, SkSamplingOptions(), &cachePaint_);
437 #endif
438         cacheBitmap_.eraseColor(0);
439     }
440 #else
441     RSBrush brush;
442     brush.SetAntiAlias(antiAlias_);
443     brush.SetColor(fillState_.GetColor().GetValue());
444     RSRect drawingRect(rect.Left(), rect.Top(), rect.Right(), rect.Bottom());
445     if (HasShadow()) {
446         RSRecordingPath path;
447         path.AddRect(drawingRect);
448         RosenDecorationPainter::PaintShadow(path, shadow_, canvas_.get());
449     }
450     if (fillState_.GetGradient().IsValid()) {
451         UpdatePaintShader(nullptr, &brush, fillState_.GetGradient());
452     }
453     if (fillState_.GetPattern().IsValid()) {
454         UpdatePaintShader(fillState_.GetPattern(), nullptr, &brush);
455     }
456     if (globalState_.HasGlobalAlpha()) {
457         brush.SetAlphaF(globalState_.GetAlpha()); // update the global alpha after setting the color
458     }
459     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
460         canvas_->AttachBrush(brush);
461         canvas_->DrawRect(drawingRect);
462         canvas_->DetachBrush();
463     } else {
464         InitCachePaint();
465         cacheCanvas_->AttachBrush(brush);
466         cacheCanvas_->DrawRect(drawingRect);
467         cacheCanvas_->DetachBrush();
468         canvas_->AttachBrush(cacheBrush_);
469         canvas_->DrawBitmap(cacheBitmap_, 0, 0);
470         canvas_->DetachBrush();
471         cacheBitmap_.ClearWithColor(RSColor::COLOR_TRANSPARENT);
472     }
473 #endif
474 }
475 
PutImageData(const ImageData & imageData)476 void RosenRenderOffscreenCanvas::PutImageData(const ImageData& imageData)
477 {
478     if (imageData.data.empty()) {
479         return;
480     }
481     uint32_t* data = new (std::nothrow)uint32_t[imageData.data.size()];
482     if (data == nullptr) {
483         return;
484     }
485 
486     for (uint32_t i = 0; i < imageData.data.size(); ++i) {
487         data[i] = imageData.data[i].GetValue();
488     }
489 #ifndef USE_ROSEN_DRAWING
490     SkBitmap skBitmap;
491     auto imageInfo = SkImageInfo::Make(imageData.dirtyWidth, imageData.dirtyHeight, SkColorType::kBGRA_8888_SkColorType,
492         SkAlphaType::kOpaque_SkAlphaType);
493     skBitmap.allocPixels(imageInfo);
494     skBitmap.setPixels(data);
495 #ifndef NEW_SKIA
496     skCanvas_->drawBitmap(skBitmap, imageData.x, imageData.y);
497 #else
498     skCanvas_->drawImage(skBitmap.asImage(), imageData.x, imageData.y, SkSamplingOptions());
499 #endif
500 #else
501     RSBitmap bitmap;
502     RSBitmapFormat format { RSColorType::COLORTYPE_BGRA_8888,
503         RSAlphaType::ALPHATYPE_OPAQUE };
504     bitmap.Build(imageData.dirtyWidth, imageData.dirtyHeight, format);
505     bitmap.SetPixels(data);
506     canvas_->DrawBitmap(bitmap, imageData.x, imageData.y);
507 #endif
508     delete[] data;
509 }
510 
SetPaintImage()511 void RosenRenderOffscreenCanvas::SetPaintImage()
512 {
513     float matrix[20] = {0};
514     matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1.0f;
515 #ifndef USE_ROSEN_DRAWING
516 #ifdef USE_SYSTEM_SKIA
517     imagePaint_.setColorFilter(SkColorFilter::MakeMatrixFilterRowMajor255(matrix));
518 #else
519     imagePaint_.setColorFilter(SkColorFilters::Matrix(matrix));
520 #endif
521 
522     imagePaint_.setMaskFilter(SkMaskFilter::MakeBlur(SkBlurStyle::kNormal_SkBlurStyle, 0));
523 #ifndef NEW_SKIA
524     imagePaint_.setImageFilter(SkBlurImageFilter::Make(0, 0, nullptr));
525 #else
526     imagePaint_.setImageFilter(SkImageFilters::Blur(0, 0, nullptr));
527 #endif
528 #else
529     auto filter = imageBrush_.GetFilter();
530     RSColorMatrix colorMatrix;
531     colorMatrix.SetArray(matrix);
532     filter.SetColorFilter(RSColorFilter::CreateMatrixColorFilter(colorMatrix));
533     filter.SetMaskFilter(RSMaskFilter::CreateBlurMaskFilter(RSBlurType::NORMAL, 0));
534     filter.SetImageFilter(RSImageFilter::CreateBlurImageFilter(0, 0, RSTileMode::DECAL, nullptr));
535     imageBrush_.SetFilter(filter);
536 #endif
537 
538     SetDropShadowFilter("0px 0px 0px black");
539     std::string filterType, filterParam;
540     if (!GetFilterType(filterType, filterParam)) {
541         return;
542     }
543     if (filterFunc_.find(filterType) != filterFunc_.end()) {
544         filterFunc_[filterType](filterParam);
545     }
546 }
547 
InitImagePaint()548 void RosenRenderOffscreenCanvas::InitImagePaint()
549 {
550 #ifndef USE_ROSEN_DRAWING
551 #ifndef NEW_SKIA
552     if (smoothingEnabled_) {
553         if (smoothingQuality_ == "low") {
554             imagePaint_.setFilterQuality(SkFilterQuality::kLow_SkFilterQuality);
555         } else if (smoothingQuality_ == "medium") {
556             imagePaint_.setFilterQuality(SkFilterQuality::kMedium_SkFilterQuality);
557         } else if (smoothingQuality_ == "high") {
558             imagePaint_.setFilterQuality(SkFilterQuality::kHigh_SkFilterQuality);
559         } else {
560             LOGE("Unsupported Quality type:%{public}s", smoothingQuality_.c_str());
561         }
562     } else {
563         imagePaint_.setFilterQuality(SkFilterQuality::kNone_SkFilterQuality);
564     }
565 #else
566     if (smoothingEnabled_) {
567         if (smoothingQuality_ == "low") {
568             options_ = SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone);
569         } else if (smoothingQuality_ == "medium") {
570             options_ = SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);
571         } else if (smoothingQuality_ == "high") {
572             options_ = SkSamplingOptions(SkCubicResampler { 1 / 3.0f, 1 / 3.0f });
573         } else {
574             LOGE("Unsupported Quality type:%{public}s", smoothingQuality_.c_str());
575         }
576     } else {
577         options_ = SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone);
578     }
579 #endif
580 #else
581     auto filter = imageBrush_.GetFilter();
582     if (smoothingEnabled_) {
583         if (smoothingQuality_ == "low") {
584             options_ = RSSamplingOptions(RSFilterMode::LINEAR, RSMipmapMode::NONE);
585             filter.SetFilterQuality(RSFilter::FilterQuality::LOW);
586             imageBrush_.SetFilter(filter);
587         } else if (smoothingQuality_ == "medium") {
588             options_ = RSSamplingOptions(RSFilterMode::LINEAR, RSMipmapMode::LINEAR);
589             filter.SetFilterQuality(RSFilter::FilterQuality::MEDIUM);
590             imageBrush_.SetFilter(filter);
591         } else if (smoothingQuality_ == "high") {
592             options_ = RSSamplingOptions(RSCubicResampler::Mitchell());
593             filter.SetFilterQuality(RSFilter::FilterQuality::HIGH);
594             imageBrush_.SetFilter(filter);
595         } else {
596             LOGE("Unsupported Quality type:%{public}s", smoothingQuality_.c_str());
597         }
598     } else {
599         options_ = RSSamplingOptions(RSFilterMode::NEAREST, RSMipmapMode::NONE);
600         filter.SetFilterQuality(RSFilter::FilterQuality::NONE);
601         imageBrush_.SetFilter(filter);
602     }
603 #endif
604     SetPaintImage();
605 }
606 
InitImageCallbacks()607 void RosenRenderOffscreenCanvas::InitImageCallbacks()
608 {
609     imageObjSuccessCallback_ = [weak = AceType::WeakClaim(this)](
610         ImageSourceInfo info, const RefPtr<ImageObject>& imageObj) {
611         auto render = weak.Upgrade();
612         if (render->loadingSource_ == info) {
613             render->ImageObjReady(imageObj);
614             return;
615         } else {
616             LOGE("image sourceInfo_ check error, : %{public}s vs %{public}s",
617                 render->loadingSource_.ToString().c_str(), info.ToString().c_str());
618         }
619     };
620 
621     failedCallback_ = [weak = AceType::WeakClaim(this)](ImageSourceInfo info, const std::string& errorMsg = "") {
622         auto render = weak.Upgrade();
623         LOGE("failedCallback_");
624         render->ImageObjFailed();
625     };
626     uploadSuccessCallback_ = [weak = AceType::WeakClaim(this)](
627         ImageSourceInfo sourceInfo, const RefPtr<NG::CanvasImage>& image) {};
628 
629     onPostBackgroundTask_ = [weak = AceType::WeakClaim(this)](CancelableTask task) {};
630 }
631 
ImageObjReady(const RefPtr<ImageObject> & imageObj)632 void RosenRenderOffscreenCanvas::ImageObjReady(const RefPtr<ImageObject>& imageObj)
633 {
634     if (imageObj->IsSvg()) {
635         skiaDom_ = AceType::DynamicCast<SvgSkiaImageObject>(imageObj)->GetSkiaDom();
636         currentSource_ = loadingSource_;
637     } else {
638         LOGE("image is not svg");
639     }
640 }
641 
ImageObjFailed()642 void RosenRenderOffscreenCanvas::ImageObjFailed()
643 {
644     loadingSource_.SetSrc("");
645     currentSource_.SetSrc("");
646     skiaDom_ = nullptr;
647 }
648 
DrawSvgImage(const CanvasImage & canvasImage)649 void RosenRenderOffscreenCanvas::DrawSvgImage(const CanvasImage& canvasImage)
650 {
651 #ifndef USE_ROSEN_DRAWING
652     const auto skCanvas =
653         globalState_.GetType() == CompositeOperation::SOURCE_OVER ? skCanvas_.get() : cacheCanvas_.get();
654 #else
655     const auto drawingCanvas =
656         globalState_.GetType() == CompositeOperation::SOURCE_OVER ? canvas_.get() : cacheCanvas_.get();
657 #endif
658 
659     // Make the ImageSourceInfo
660     canvasImage_ = canvasImage;
661     loadingSource_ = ImageSourceInfo(canvasImage.src);
662 
663     // get the ImageObject
664     if (currentSource_ != loadingSource_) {
665         ImageProvider::FetchImageObject(loadingSource_, imageObjSuccessCallback_, uploadSuccessCallback_,
666             failedCallback_, pipelineContext_, true, true, true, onPostBackgroundTask_);
667     }
668 
669     // draw the svg
670 #ifndef USE_ROSEN_DRAWING
671     if (skiaDom_) {
672         SkRect srcRect;
673         SkRect dstRect;
674         Offset startPoint;
675         double scaleX = 1.0f;
676         double scaleY = 1.0f;
677         switch (canvasImage.flag) {
678             case 0:
679                 srcRect = SkRect::MakeXYWH(0, 0, skiaDom_->containerSize().width(), skiaDom_->containerSize().height());
680                 dstRect = SkRect::MakeXYWH(canvasImage.dx, canvasImage.dy,
681                     skiaDom_->containerSize().width(), skiaDom_->containerSize().height());
682                 break;
683             case 1: {
684                 srcRect = SkRect::MakeXYWH(0, 0, skiaDom_->containerSize().width(), skiaDom_->containerSize().height());
685                 dstRect = SkRect::MakeXYWH(canvasImage.dx, canvasImage.dy, canvasImage.dWidth, canvasImage.dHeight);
686                 break;
687             }
688             case 2: {
689                 srcRect = SkRect::MakeXYWH(canvasImage.sx, canvasImage.sy, canvasImage.sWidth, canvasImage.sHeight);
690                 dstRect = SkRect::MakeXYWH(canvasImage.dx, canvasImage.dy, canvasImage.dWidth, canvasImage.dHeight);
691                 break;
692             }
693             default:
694                 break;
695         }
696         scaleX = dstRect.width() / srcRect.width();
697         scaleY = dstRect.height() / srcRect.height();
698         startPoint = Offset(dstRect.left(), dstRect.top())
699            - Offset(srcRect.left() * scaleX, srcRect.top() * scaleY);
700 
701         skCanvas->save();
702         skCanvas->clipRect(dstRect);
703         skCanvas->translate(startPoint.GetX(), startPoint.GetY());
704         skCanvas->scale(scaleX, scaleY);
705         skiaDom_->render(skCanvas);
706         skCanvas->restore();
707     }
708 #else
709     if (skiaDom_) {
710         RSRect srcRect;
711         RSRect dstRect;
712         Offset startPoint;
713         double scaleX = 1.0f;
714         double scaleY = 1.0f;
715         switch (canvasImage.flag) {
716             case 0:
717                 srcRect = RSRect(0, 0, skiaDom_->containerSize().width(), skiaDom_->containerSize().height());
718                 dstRect = RSRect(canvasImage.dx, canvasImage.dy, skiaDom_->containerSize().width() + canvasImage.dx,
719                     skiaDom_->containerSize().height() + canvasImage.dy);
720                 break;
721             case 1: {
722                 srcRect = RSRect(0, 0, skiaDom_->containerSize().width(), skiaDom_->containerSize().height());
723                 dstRect = RSRect(canvasImage.dx, canvasImage.dy,
724                     canvasImage.dWidth + canvasImage.dx, canvasImage.dHeight + canvasImage.dy);
725                 break;
726             }
727             case 2: {
728                 srcRect = RSRect(canvasImage.sx, canvasImage.sy,
729                     canvasImage.sWidth + canvasImage.sx, canvasImage.sHeight + canvasImage.sy);
730                 dstRect = RSRect(canvasImage.dx, canvasImage.dy,
731                     canvasImage.dWidth + canvasImage.dx, canvasImage.dHeight + canvasImage.dy);
732                 break;
733             }
734             default:
735                 break;
736         }
737         scaleX = dstRect.GetWidth() / srcRect.GetWidth();
738         scaleY = dstRect.GetHeight() / srcRect.GetHeight();
739         startPoint =
740             Offset(dstRect.GetLeft(), dstRect.GetTop()) - Offset(srcRect.GetLeft() * scaleX, srcRect.GetTop() * scaleY);
741 
742         drawingCanvas->Save();
743         drawingCanvas->ClipRect(dstRect, RSClipOp::INTERSECT, false);
744         drawingCanvas->Translate(startPoint.GetX(), startPoint.GetY());
745         drawingCanvas->Scale(scaleX, scaleY);
746         drawingCanvas->DrawSVGDOM(skiaDom_);
747         drawingCanvas->Restore();
748     }
749 #endif
750 }
751 
DrawImage(const CanvasImage & canvasImage,double width,double height)752 void RosenRenderOffscreenCanvas::DrawImage(const CanvasImage& canvasImage, double width, double height)
753 {
754     auto context = pipelineContext_.Upgrade();
755     if (!context) {
756         return;
757     }
758 
759     std::string::size_type tmp = canvasImage.src.find(".svg");
760     if (tmp != std::string::npos) {
761         DrawSvgImage(canvasImage);
762         return;
763     }
764 
765 #ifndef USE_ROSEN_DRAWING
766     auto image = GreatOrEqual(width, 0) && GreatOrEqual(height, 0)
767                         ? ImageProvider::GetSkImage(canvasImage.src, context, Size(width, height))
768                         : ImageProvider::GetSkImage(canvasImage.src, context);
769     if (!image) {
770         LOGE("image is null");
771         return;
772     }
773     InitCachePaint();
774     const auto skCanvas =
775         globalState_.GetType() == CompositeOperation::SOURCE_OVER ? skCanvas_.get() : cacheCanvas_.get();
776     InitImagePaint();
777     if (HasImageShadow()) {
778         SkRect skRect = SkRect::MakeXYWH(canvasImage.dx, canvasImage.dy, canvasImage.dWidth, canvasImage.dHeight);
779         SkPath path;
780         path.addRect(skRect);
781 #ifndef NEW_SKIA
782         FlutterDecorationPainter::PaintShadow(path, imageShadow_, skCanvas);
783 #else
784         RosenDecorationPainter::PaintShadow(path, imageShadow_, skCanvas);
785 #endif
786     }
787     switch (canvasImage.flag) {
788         case 0:
789             skCanvas->drawImage(image, canvasImage.dx, canvasImage.dy);
790             break;
791         case 1: {
792             SkRect rect = SkRect::MakeXYWH(canvasImage.dx, canvasImage.dy, canvasImage.dWidth, canvasImage.dHeight);
793 #ifndef NEW_SKIA
794             skCanvas->drawImageRect(image, rect, &imagePaint_);
795 #else
796             skCanvas->drawImageRect(image, rect, options_, &imagePaint_);
797 #endif
798             break;
799         }
800         case 2: {
801             SkRect dstRect =
802                 SkRect::MakeXYWH(canvasImage.dx, canvasImage.dy, canvasImage.dWidth, canvasImage.dHeight);
803             SkRect srcRect =
804                 SkRect::MakeXYWH(canvasImage.sx, canvasImage.sy, canvasImage.sWidth, canvasImage.sHeight);
805 #ifndef NEW_SKIA
806             skCanvas->drawImageRect(image, srcRect, dstRect, &imagePaint_);
807 #else
808             skCanvas->drawImageRect(image, srcRect, dstRect, options_, &imagePaint_, SkCanvas::kFast_SrcRectConstraint);
809 #endif
810             break;
811         }
812         default:
813             break;
814     }
815     if (globalState_.GetType() != CompositeOperation::SOURCE_OVER) {
816 #ifndef NEW_SKIA
817         skCanvas_->drawBitmap(cacheBitmap_, 0, 0, &cachePaint_);
818 #else
819         skCanvas_->drawImage(cacheBitmap_.asImage(), 0, 0, SkSamplingOptions(), &cachePaint_);
820 #endif
821         cacheBitmap_.eraseColor(0);
822     }
823 #else
824     auto image = GreatOrEqual(width, 0) && GreatOrEqual(height, 0)
825                         ? ImageProvider::GetDrawingImage(canvasImage.src, context, Size(width, height))
826                         : ImageProvider::GetDrawingImage(canvasImage.src, context);
827     if (!image) {
828         LOGE("image is null");
829         return;
830     }
831     InitCachePaint();
832     const auto canvas =
833         globalState_.GetType() == CompositeOperation::SOURCE_OVER ? canvas_.get() : cacheCanvas_.get();
834     InitImagePaint();
835     if (HasImageShadow()) {
836         RSRect drawingRect = RSRect(canvasImage.dx, canvasImage.dy,
837             canvasImage.dWidth + canvasImage.dx, canvasImage.dHeight + canvasImage.dy);
838         RSRecordingPath path;
839         path.AddRect(drawingRect);
840         RosenDecorationPainter::PaintShadow(path, imageShadow_, canvas);
841     }
842 
843     switch (canvasImage.flag) {
844         case 0:
845             canvas->DrawImage(*image, canvasImage.dx, canvasImage.dy, RSSamplingOptions());
846             break;
847         case 1: {
848             RSRect rect =
849                 RSRect(canvasImage.dx, canvasImage.dy,
850                     canvasImage.dWidth + canvasImage.dx, canvasImage.dHeight + canvasImage.dy);
851             canvas->AttachBrush(imageBrush_);
852             canvas->DrawImageRect(*image, rect, options_);
853             canvas->DetachBrush();
854             break;
855         }
856         case 2: {
857             RSRect dstRect = RSRect(canvasImage.dx, canvasImage.dy,
858                 canvasImage.dWidth + canvasImage.dx, canvasImage.dHeight + canvasImage.dy);
859             RSRect srcRect = RSRect(canvasImage.sx, canvasImage.sy,
860                 canvasImage.sWidth + canvasImage.sx, canvasImage.sHeight + canvasImage.sy);
861             canvas->AttachBrush(imageBrush_);
862             canvas->DrawImageRect(*image, srcRect, dstRect, options_, RSSrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
863             canvas->DetachBrush();
864             break;
865         }
866         default:
867             break;
868     }
869     if (globalState_.GetType() != CompositeOperation::SOURCE_OVER) {
870         canvas_->AttachBrush(cacheBrush_);
871         canvas_->DrawBitmap(cacheBitmap_, 0, 0);
872         canvas_->DetachBrush();
873         cacheBitmap_.ClearWithColor(RSColor::COLOR_TRANSPARENT);
874     }
875 #endif
876 }
877 
DrawPixelMap(RefPtr<PixelMap> pixelMap,const CanvasImage & canvasImage)878 void RosenRenderOffscreenCanvas::DrawPixelMap(RefPtr<PixelMap> pixelMap, const CanvasImage& canvasImage)
879 {
880     auto context = pipelineContext_.Upgrade();
881     if (!context) {
882         return;
883     }
884 
885 #ifndef USE_ROSEN_DRAWING
886     // get skImage form pixelMap
887     auto imageInfo = ImageProvider::MakeSkImageInfoFromPixelMap(pixelMap);
888     SkPixmap imagePixmap(imageInfo, reinterpret_cast<const void*>(pixelMap->GetPixels()), pixelMap->GetRowBytes());
889 
890     // Step2: Create SkImage and draw it, using gpu or cpu
891     sk_sp<SkImage> image;
892 
893     image = SkImage::MakeFromRaster(imagePixmap, &PixelMap::ReleaseProc, PixelMap::GetReleaseContext(pixelMap));
894     if (!image) {
895         LOGE("image is null");
896         return;
897     }
898 
899     InitCachePaint();
900     const auto skCanvas =
901         globalState_.GetType() == CompositeOperation::SOURCE_OVER ? skCanvas_.get() : cacheCanvas_.get();
902     InitImagePaint();
903     switch (canvasImage.flag) {
904         case 0:
905             skCanvas->drawImage(image, canvasImage.dx, canvasImage.dy);
906             break;
907         case 1: {
908             SkRect rect = SkRect::MakeXYWH(canvasImage.dx, canvasImage.dy, canvasImage.dWidth, canvasImage.dHeight);
909 #ifndef NEW_SKIA
910             skCanvas->drawImageRect(image, rect, &imagePaint_);
911 #else
912             skCanvas->drawImageRect(image, rect, options_, &imagePaint_);
913 #endif
914             break;
915         }
916         case 2: {
917             SkRect dstRect =
918                 SkRect::MakeXYWH(canvasImage.dx, canvasImage.dy, canvasImage.dWidth, canvasImage.dHeight);
919             SkRect srcRect =
920                 SkRect::MakeXYWH(canvasImage.sx, canvasImage.sy, canvasImage.sWidth, canvasImage.sHeight);
921 #ifndef NEW_SKIA
922             skCanvas->drawImageRect(image, srcRect, dstRect, &imagePaint_);
923 #else
924             skCanvas->drawImageRect(image, srcRect, dstRect, options_, &imagePaint_, SkCanvas::kFast_SrcRectConstraint);
925 #endif
926             break;
927         }
928         default:
929             break;
930     }
931     if (globalState_.GetType() != CompositeOperation::SOURCE_OVER) {
932 #ifndef NEW_SKIA
933         skCanvas_->drawBitmap(cacheBitmap_, 0, 0, &cachePaint_);
934 #else
935         skCanvas_->drawImage(cacheBitmap_.asImage(), 0, 0, SkSamplingOptions(), &cachePaint_);
936 #endif
937         cacheBitmap_.eraseColor(0);
938     }
939 #else
940     // get Image form pixelMap
941     auto rsBitmapFormat = ImageProvider::MakeRSBitmapFormatFromPixelMap(pixelMap);
942     auto rsBitmap = std::make_shared<RSBitmap>();
943     rsBitmap->Build(pixelMap->GetWidth(), pixelMap->GetHeight(), rsBitmapFormat);
944     rsBitmap->SetPixels(const_cast<void*>(reinterpret_cast<const void*>(pixelMap->GetPixels())));
945 
946     // Step2: Create Image and draw it, using gpu or cpu
947     auto image = std::make_shared<RSImage>();
948     if (!image->BuildFromBitmap(*rsBitmap)) {
949         LOGE("image is null");
950         return;
951     }
952 
953     InitCachePaint();
954     const auto drawingCanvas =
955         globalState_.GetType() == CompositeOperation::SOURCE_OVER ? canvas_.get() : cacheCanvas_.get();
956     InitImagePaint();
957     switch (canvasImage.flag) {
958         case 0:
959             drawingCanvas->DrawImage(*image, canvasImage.dx, canvasImage.dy, RSSamplingOptions());
960             break;
961         case 1: {
962             RSRect rect = RSRect(canvasImage.dx, canvasImage.dy,
963                 canvasImage.dWidth + canvasImage.dx, canvasImage.dHeight + canvasImage.dy);
964             drawingCanvas->AttachBrush(imageBrush_);
965             drawingCanvas->DrawImageRect(*image, rect, options_);
966             drawingCanvas->DetachBrush();
967             break;
968         }
969         case 2: {
970             RSRect dstRect = RSRect(canvasImage.dx, canvasImage.dy,
971                 canvasImage.dWidth + canvasImage.dx, canvasImage.dHeight + canvasImage.dy);
972             RSRect srcRect = RSRect(canvasImage.sx, canvasImage.sy,
973                 canvasImage.sWidth + canvasImage.sx, canvasImage.sHeight + canvasImage.sy);
974             drawingCanvas->AttachBrush(imageBrush_);
975             drawingCanvas->DrawImageRect(*image, srcRect, dstRect, options_,
976                 RSSrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
977             drawingCanvas->DetachBrush();
978             break;
979         }
980         default:
981             break;
982     }
983     if (globalState_.GetType() != CompositeOperation::SOURCE_OVER) {
984         canvas_->AttachBrush(cacheBrush_);
985         canvas_->DrawBitmap(cacheBitmap_, 0, 0);
986         canvas_->DetachBrush();
987         cacheBitmap_.ClearWithColor(RSColor::COLOR_TRANSPARENT);
988     }
989 #endif
990 }
991 
GetImageData(double left,double top,double width,double height)992 std::unique_ptr<ImageData> RosenRenderOffscreenCanvas::GetImageData(double left, double top,
993     double width, double height)
994 {
995     double viewScale = 1.0;
996     auto pipeline = pipelineContext_.Upgrade();
997     if (pipeline) {
998         viewScale = pipeline->GetViewScale();
999     }
1000     // copy the bitmap to tempCanvas
1001 #ifndef USE_ROSEN_DRAWING
1002     auto imageInfo =
1003         SkImageInfo::Make(width, height, SkColorType::kBGRA_8888_SkColorType, SkAlphaType::kOpaque_SkAlphaType);
1004     double scaledLeft = left * viewScale;
1005     double scaledTop = top * viewScale;
1006     double dirtyWidth = width >= 0 ? width : 0;
1007     double dirtyHeight = height >= 0 ? height : 0;
1008     int32_t size = dirtyWidth * dirtyHeight;
1009     auto srcRect = SkRect::MakeXYWH(scaledLeft, scaledTop, width * viewScale, height * viewScale);
1010     auto dstRect = SkRect::MakeXYWH(0.0, 0.0, dirtyWidth, dirtyHeight);
1011     SkBitmap tempCache;
1012     tempCache.allocPixels(imageInfo);
1013     SkCanvas tempCanvas(tempCache);
1014 #if defined (USE_SYSTEM_SKIA_S) || defined (NEW_SKIA)
1015     tempCanvas.drawImageRect(
1016         skBitmap_.asImage(), srcRect, dstRect, options_, nullptr, SkCanvas::kFast_SrcRectConstraint);
1017 #else
1018     tempCanvas.drawBitmapRect(skBitmap_, srcRect, dstRect, nullptr);
1019 #endif
1020     // write color
1021     std::unique_ptr<uint8_t[]> pixels = std::make_unique<uint8_t[]>(size * 4);
1022     tempCanvas.readPixels(imageInfo, pixels.get(), dirtyWidth * imageInfo.bytesPerPixel(), 0, 0);
1023 #else
1024     RSBitmapFormat format { RSColorType::COLORTYPE_BGRA_8888, RSAlphaType::ALPHATYPE_OPAQUE };
1025     double scaledLeft = left * viewScale;
1026     double scaledTop = top * viewScale;
1027     double dirtyWidth = width >= 0 ? width : 0;
1028     double dirtyHeight = height >= 0 ? height : 0;
1029     int32_t size = dirtyWidth * dirtyHeight;
1030     auto srcRect = RSRect(scaledLeft, scaledTop, width * viewScale + scaledLeft, height * viewScale + scaledTop);
1031     auto dstRect = RSRect(0.0, 0.0, dirtyWidth, dirtyHeight);
1032     RSBitmap tempCache;
1033     tempCache.Build(width, height, format);
1034     RSCanvas tempCanvas;
1035     tempCanvas.Bind(tempCache);
1036     RSImage rsImage;
1037     rsImage.BuildFromBitmap(bitmap_);
1038     tempCanvas.DrawImageRect(rsImage, srcRect, dstRect, options_, RSSrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
1039     // write color
1040     uint8_t* pixels = static_cast<uint8_t*>(tempCache.GetPixels());
1041 #endif
1042     std::unique_ptr<ImageData> imageData = std::make_unique<ImageData>();
1043     imageData->dirtyWidth = dirtyWidth;
1044     imageData->dirtyHeight = dirtyHeight;
1045     // a pixel include 4 data blue, green, red, alpha
1046     for (int i = 0; i < size * 4; i += 4) {
1047         auto blue = pixels[i];
1048         auto green = pixels[i + 1];
1049         auto red = pixels[i + 2];
1050         auto alpha = pixels[i + 3];
1051         imageData->data.emplace_back(Color::FromARGB(alpha, red, green, blue));
1052     }
1053     return imageData;
1054 }
1055 
Save()1056 void RosenRenderOffscreenCanvas::Save()
1057 {
1058     SaveStates();
1059 #ifndef USE_ROSEN_DRAWING
1060     skCanvas_->save();
1061 #else
1062     canvas_->Save();
1063 #endif
1064 }
1065 
Restore()1066 void RosenRenderOffscreenCanvas::Restore()
1067 {
1068     RestoreStates();
1069 #ifndef USE_ROSEN_DRAWING
1070     skCanvas_->restore();
1071 #else
1072     canvas_->Restore();
1073 #endif
1074 }
1075 
ToDataURL(const std::string & type,const double quality)1076 std::string RosenRenderOffscreenCanvas::ToDataURL(const std::string& type, const double quality)
1077 {
1078     auto pipeline = pipelineContext_.Upgrade();
1079     if (!pipeline) {
1080         return UNSUPPORTED;
1081     }
1082     std::string mimeType = GetMimeType(type);
1083     double qua = GetQuality(type, quality);
1084 #ifndef USE_ROSEN_DRAWING
1085     SkBitmap tempCache;
1086     tempCache.allocPixels(SkImageInfo::Make(width_, height_, SkColorType::kBGRA_8888_SkColorType,
1087         (mimeType == IMAGE_JPEG) ? SkAlphaType::kOpaque_SkAlphaType : SkAlphaType::kUnpremul_SkAlphaType));
1088     SkCanvas tempCanvas(tempCache);
1089     double viewScale = pipeline->GetViewScale();
1090     tempCanvas.clear(SK_ColorTRANSPARENT);
1091     tempCanvas.scale(1.0 / viewScale, 1.0 / viewScale);
1092 #if defined(USE_SYSTEM_SKIA_S) || defined (NEW_SKIA)
1093     //The return value of the dual framework interface has no alpha
1094     tempCanvas.drawImage(skBitmap_.asImage(), 0.0f, 0.0f);
1095 #else
1096     tempCanvas.drawBitmap(skBitmap_, 0.0f, 0.0f);
1097 #endif
1098     SkPixmap src;
1099     bool success = tempCache.peekPixels(&src);
1100 #else
1101     RSBitmap tempCache;
1102     tempCache.Build(width_, height_, { RSColorType::COLORTYPE_BGRA_8888,
1103         (mimeType == IMAGE_JPEG) ? RSAlphaType::ALPHATYPE_OPAQUE : RSAlphaType::ALPHATYPE_UNPREMUL });
1104     RSCanvas tempCanvas;
1105     tempCanvas.Bind(tempCache);
1106     double viewScale = pipeline->GetViewScale();
1107     tempCanvas.Clear(RSColor::COLOR_TRANSPARENT);
1108     tempCanvas.Scale(1.0 / viewScale, 1.0 / viewScale);
1109     tempCanvas.DrawBitmap(bitmap_, 0.0f, 0.0f);
1110 
1111     auto& skBitmap = tempCache.GetImpl<Rosen::Drawing::SkiaBitmap>()->ExportSkiaBitmap();
1112     SkPixmap src;
1113     bool success = skBitmap.peekPixels(&src);
1114 #endif
1115     if (!success) {
1116         LOGE("ToDataURL failed,the bitmap does not have access to pixel data");
1117         return UNSUPPORTED;
1118     }
1119     SkDynamicMemoryWStream dst;
1120     if (mimeType == IMAGE_JPEG) {
1121         SkJpegEncoder::Options options;
1122         options.fQuality = qua;
1123         success = SkJpegEncoder::Encode(&dst, src, options);
1124     } else if (mimeType == IMAGE_WEBP) {
1125         SkWebpEncoder::Options options;
1126         options.fQuality = qua * 100.0;
1127         success = SkWebpEncoder::Encode(&dst, src, options);
1128     } else {
1129         mimeType = IMAGE_PNG;
1130         SkPngEncoder::Options options;
1131         success = SkPngEncoder::Encode(&dst, src, options);
1132     }
1133     if (!success) {
1134         LOGE("ToDataURL failed,image encoding failed");
1135         return UNSUPPORTED;
1136     }
1137     auto result = dst.detachAsData();
1138     if (result == nullptr) {
1139         LOGE("DetachAsData failed when ToDataURL.");
1140         return UNSUPPORTED;
1141     }
1142     size_t len = SkBase64::Encode(result->data(), result->size(), nullptr);
1143     if (len > MAX_LENGTH) {
1144         LOGE("ToDataURL failed,The resolution of the image is greater than the maximum allowed resolution");
1145         return UNSUPPORTED;
1146     }
1147     SkString info(len);
1148     SkBase64::Encode(result->data(), result->size(), info.writable_str());
1149     return std::string(URL_PREFIX).append(mimeType).append(URL_SYMBOL).append(info.c_str());
1150 }
1151 
1152 #ifndef USE_ROSEN_DRAWING
UpdatePaintShader(SkPaint & paint,const Gradient & gradient)1153 void RosenRenderOffscreenCanvas::UpdatePaintShader(SkPaint& paint, const Gradient& gradient)
1154 {
1155     SkPoint beginPoint = SkPoint::Make(SkDoubleToScalar(gradient.GetBeginOffset().GetX()),
1156         SkDoubleToScalar(gradient.GetBeginOffset().GetY()));
1157     SkPoint endPoint = SkPoint::Make(SkDoubleToScalar(gradient.GetEndOffset().GetX()),
1158         SkDoubleToScalar(gradient.GetEndOffset().GetY()));
1159     SkPoint pts[2] = { beginPoint, endPoint };
1160     std::vector<GradientColor> gradientColors = gradient.GetColors();
1161     std::stable_sort(gradientColors.begin(), gradientColors.end(),
1162         [](auto& colorA, auto& colorB) { return colorA.GetDimension() < colorB.GetDimension(); });
1163     uint32_t colorsSize = gradientColors.size();
1164     SkColor colors[gradientColors.size()];
1165     float pos[gradientColors.size()];
1166     for (uint32_t i = 0; i < colorsSize; ++i) {
1167         const auto& gradientColor = gradientColors[i];
1168         colors[i] = gradientColor.GetColor().GetValue();
1169         pos[i] = gradientColor.GetDimension().Value();
1170     }
1171 
1172 #ifdef USE_SYSTEM_SKIA
1173     auto mode = SkShader::kClamp_TileMode;
1174 #else
1175     auto mode = SkTileMode::kClamp;
1176 #endif
1177 
1178     sk_sp<SkShader> skShader = nullptr;
1179     if (gradient.GetType() == GradientType::LINEAR) {
1180         skShader = SkGradientShader::MakeLinear(pts, colors, pos, gradientColors.size(), mode);
1181     } else {
1182         if (gradient.GetInnerRadius() <= 0.0 && beginPoint == endPoint) {
1183             skShader = SkGradientShader::MakeRadial(
1184                 endPoint, gradient.GetOuterRadius(), colors, pos, gradientColors.size(), mode);
1185         } else {
1186             skShader = SkGradientShader::MakeTwoPointConical(beginPoint, gradient.GetInnerRadius(),
1187                 endPoint, gradient.GetOuterRadius(), colors, pos, gradientColors.size(), mode);
1188         }
1189     }
1190     paint.setShader(skShader);
1191 }
1192 #else
UpdatePaintShader(RSPen * pen,RSBrush * brush,const Gradient & gradient)1193 void RosenRenderOffscreenCanvas::UpdatePaintShader(RSPen* pen, RSBrush* brush, const Gradient& gradient)
1194 {
1195     RSPoint beginPoint =
1196         RSPoint(static_cast<RSScalar>(gradient.GetBeginOffset().GetX()),
1197             static_cast<RSScalar>(gradient.GetBeginOffset().GetY()));
1198     RSPoint endPoint =
1199         RSPoint(static_cast<RSScalar>(gradient.GetEndOffset().GetX()),
1200             static_cast<RSScalar>(gradient.GetEndOffset().GetY()));
1201     std::vector<RSPoint> pts = { beginPoint, endPoint };
1202     auto gradientColors = gradient.GetColors();
1203     std::stable_sort(gradientColors.begin(), gradientColors.end(),
1204         [](auto& colorA, auto& colorB) { return colorA.GetDimension() < colorB.GetDimension(); });
1205     uint32_t colorsSize = gradientColors.size();
1206     std::vector<RSColorQuad> colors(gradientColors.size(), 0);
1207     std::vector<RSScalar> pos(gradientColors.size(), 0);
1208     for (uint32_t i = 0; i < colorsSize; ++i) {
1209         const auto& gradientColor = gradientColors[i];
1210         colors.at(i) = gradientColor.GetColor().GetValue();
1211         pos.at(i) = gradientColor.GetDimension().Value();
1212     }
1213 
1214     auto mode = RSTileMode::CLAMP;
1215     std::shared_ptr<RSShaderEffect> shaderEffect = nullptr;
1216     if (gradient.GetType() == GradientType::LINEAR) {
1217         shaderEffect = RSShaderEffect::CreateLinearGradient(pts.at(0), pts.at(1), colors, pos, mode);
1218     } else {
1219         if (gradient.GetInnerRadius() <= 0.0 && beginPoint == endPoint) {
1220             shaderEffect = RSShaderEffect::CreateRadialGradient(
1221                 pts.at(1), gradient.GetOuterRadius(), colors, pos, mode);
1222         } else {
1223             shaderEffect = RSShaderEffect::CreateTwoPointConical(
1224                 pts.at(0), gradient.GetInnerRadius(), pts.at(1), gradient.GetOuterRadius(), colors, pos, mode);
1225         }
1226     }
1227     if (pen) {
1228         pen->SetShaderEffect(shaderEffect);
1229     }
1230     if (brush) {
1231         brush->SetShaderEffect(shaderEffect);
1232     }
1233 }
1234 #endif
1235 
BeginPath()1236 void RosenRenderOffscreenCanvas::BeginPath()
1237 {
1238 #ifndef USE_ROSEN_DRAWING
1239     skPath_.reset();
1240 #else
1241     path_.Reset();
1242 #endif
1243 }
1244 
ResetTransform()1245 void RosenRenderOffscreenCanvas::ResetTransform()
1246 {
1247 #ifndef USE_ROSEN_DRAWING
1248     skCanvas_->resetMatrix();
1249 #else
1250     canvas_->ResetMatrix();
1251 #endif
1252 }
1253 
1254 #ifndef USE_ROSEN_DRAWING
UpdatePaintShader(const Pattern & pattern,SkPaint & paint)1255 void RosenRenderOffscreenCanvas::UpdatePaintShader(const Pattern& pattern, SkPaint& paint)
1256 {
1257     auto context = pipelineContext_.Upgrade();
1258     if (!context) {
1259         return;
1260     }
1261 
1262     auto width = pattern.GetImageWidth();
1263     auto height = pattern.GetImageHeight();
1264     auto image = GreatOrEqual(width, 0) && GreatOrEqual(height, 0)
1265                         ? ImageProvider::GetSkImage(pattern.GetImgSrc(), context, Size(width, height))
1266                         : ImageProvider::GetSkImage(pattern.GetImgSrc(), context);
1267     if (!image) {
1268         LOGE("image is null");
1269         return;
1270     }
1271     static const LinearMapNode<void (*)(sk_sp<SkImage>, SkPaint&)> staticPattern[] = {
1272         { "no-repeat",
1273             [](sk_sp<SkImage> image, SkPaint& paint) {
1274 #ifdef USE_SYSTEM_SKIA
1275                 paint.setShader(image->makeShader(SkShader::kDecal_TileMode, SkShader::kDecal_TileMode, nullptr));
1276 #elif defined(NEW_SKIA)
1277                 paint.setShader(image->makeShader(SkTileMode::kDecal, SkTileMode::kDecal, SkSamplingOptions(), nullptr));
1278 #else
1279                 paint.setShader(image->makeShader(SkTileMode::kDecal, SkTileMode::kDecal, nullptr));
1280 #endif
1281             } },
1282         { "repeat",
1283             [](sk_sp<SkImage> image, SkPaint& paint) {
1284 #ifdef USE_SYSTEM_SKIA
1285                 paint.setShader(image->makeShader(SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, nullptr));
1286 #elif defined(NEW_SKIA)
1287                 paint.setShader(image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, SkSamplingOptions(), nullptr));
1288 #else
1289                 paint.setShader(image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, nullptr));
1290 #endif
1291             } },
1292         { "repeat-x",
1293             [](sk_sp<SkImage> image, SkPaint& paint) {
1294 #ifdef USE_SYSTEM_SKIA
1295                 paint.setShader(image->makeShader(SkShader::kRepeat_TileMode, SkShader::kDecal_TileMode, nullptr));
1296 #elif defined(NEW_SKIA)
1297                 paint.setShader(image->makeShader(SkTileMode::kRepeat, SkTileMode::kDecal, SkSamplingOptions(), nullptr));
1298 #else
1299                 paint.setShader(image->makeShader(SkTileMode::kRepeat, SkTileMode::kDecal, nullptr));
1300 #endif
1301             } },
1302         { "repeat-y",
1303             [](sk_sp<SkImage> image, SkPaint& paint) {
1304 #ifdef USE_SYSTEM_SKIA
1305                 paint.setShader(image->makeShader(SkShader::kDecal_TileMode, SkShader::kRepeat_TileMode, nullptr));
1306 #elif defined(NEW_SKIA)
1307                 paint.setShader(image->makeShader(SkTileMode::kDecal, SkTileMode::kRepeat, SkSamplingOptions(), nullptr));
1308 #else
1309                 paint.setShader(image->makeShader(SkTileMode::kDecal, SkTileMode::kRepeat, nullptr));
1310 #endif
1311             } },
1312     };
1313     auto operatorIter =
1314         BinarySearchFindIndex(staticPattern, ArraySize(staticPattern), pattern.GetRepetition().c_str());
1315     if (operatorIter != -1) {
1316         staticPattern[operatorIter].value(image, paint);
1317     }
1318 }
1319 #else
UpdatePaintShader(const Pattern & pattern,RSPen * pen,RSBrush * brush)1320 void RosenRenderOffscreenCanvas::UpdatePaintShader(const Pattern& pattern, RSPen* pen, RSBrush* brush)
1321 {
1322     auto context = pipelineContext_.Upgrade();
1323     if (!context) {
1324         return;
1325     }
1326 
1327     auto width = pattern.GetImageWidth();
1328     auto height = pattern.GetImageHeight();
1329     auto image = GreatOrEqual(width, 0) && GreatOrEqual(height, 0)
1330                      ? ImageProvider::GetDrawingImage(pattern.GetImgSrc(), context, Size(width, height))
1331                      : ImageProvider::GetDrawingImage(pattern.GetImgSrc(), context);
1332     if (!image) {
1333         LOGE("image is null");
1334         return;
1335     }
1336     static const LinearMapNode<void (*)(std::shared_ptr<RSImage>&, std::shared_ptr<RSShaderEffect>&)>
1337         staticPattern[] = {
1338             { "no-repeat",
1339                 [](std::shared_ptr<RSImage>& image, std::shared_ptr<RSShaderEffect>& rsShaderEffect) {
1340                     rsShaderEffect = RSShaderEffect::CreateImageShader(*image,
1341                         RSTileMode::DECAL, RSTileMode::DECAL, RSSamplingOptions(), RSMatrix());
1342                 } },
1343             { "repeat",
1344                 [](std::shared_ptr<RSImage>& image, std::shared_ptr<RSShaderEffect>& rsShaderEffect) {
1345                     rsShaderEffect = RSShaderEffect::CreateImageShader(*image,
1346                         RSTileMode::REPEAT, RSTileMode::REPEAT, RSSamplingOptions(), RSMatrix());
1347                 } },
1348             { "repeat-x",
1349                 [](std::shared_ptr<RSImage>& image, std::shared_ptr<RSShaderEffect>& rsShaderEffect) {
1350                     rsShaderEffect = RSShaderEffect::CreateImageShader(*image,
1351                         RSTileMode::REPEAT, RSTileMode::DECAL, RSSamplingOptions(), RSMatrix());
1352                 } },
1353             { "repeat-y",
1354                 [](std::shared_ptr<RSImage>& image, std::shared_ptr<RSShaderEffect>& rsShaderEffect) {
1355                     rsShaderEffect = RSShaderEffect::CreateImageShader(*image,
1356                         RSTileMode::DECAL, RSTileMode::REPEAT, RSSamplingOptions(), RSMatrix());
1357                 } },
1358         };
1359     auto operatorIter = BinarySearchFindIndex(staticPattern, ArraySize(staticPattern), pattern.GetRepetition().c_str());
1360     if (operatorIter != -1) {
1361         std::shared_ptr<RSShaderEffect> shaderEffect = nullptr;
1362         staticPattern[operatorIter].value(image, shaderEffect);
1363         if (pen) {
1364             pen->SetShaderEffect(shaderEffect);
1365         }
1366         if (brush) {
1367             brush->SetShaderEffect(shaderEffect);
1368         }
1369     }
1370 }
1371 #endif
1372 
Arc(const ArcParam & param)1373 void RosenRenderOffscreenCanvas::Arc(const ArcParam& param)
1374 {
1375     double left = param.x - param.radius;
1376     double top = param.y - param.radius;
1377     double right = param.x + param.radius;
1378     double bottom = param.y + param.radius;
1379     double startAngle = param.startAngle * HALF_CIRCLE_ANGLE / M_PI;
1380     double endAngle = param.endAngle * HALF_CIRCLE_ANGLE / M_PI;
1381     double sweepAngle = endAngle - startAngle;
1382     if (param.anticlockwise) {
1383         sweepAngle =
1384             endAngle > startAngle ? (std::fmod(sweepAngle, FULL_CIRCLE_ANGLE) - FULL_CIRCLE_ANGLE) : sweepAngle;
1385     } else {
1386         sweepAngle =
1387             endAngle > startAngle ? sweepAngle : (std::fmod(sweepAngle, FULL_CIRCLE_ANGLE) + FULL_CIRCLE_ANGLE);
1388     }
1389 #ifndef USE_ROSEN_DRAWING
1390     auto rect = SkRect::MakeLTRB(left, top, right, bottom);
1391     if (NearEqual(std::fmod(sweepAngle, FULL_CIRCLE_ANGLE), 0.0) && !NearEqual(startAngle, endAngle)) {
1392         // draw circle
1393         double half = GreatNotEqual(sweepAngle, 0.0) ? HALF_CIRCLE_ANGLE : -HALF_CIRCLE_ANGLE;
1394         skPath_.arcTo(rect, SkDoubleToScalar(startAngle), SkDoubleToScalar(half), false);
1395         skPath_.arcTo(rect, SkDoubleToScalar(half + startAngle), SkDoubleToScalar(half), false);
1396     } else if (!NearEqual(std::fmod(sweepAngle, FULL_CIRCLE_ANGLE), 0.0) && abs(sweepAngle) > FULL_CIRCLE_ANGLE) {
1397         double half = GreatNotEqual(sweepAngle, 0.0) ? HALF_CIRCLE_ANGLE : -HALF_CIRCLE_ANGLE;
1398         skPath_.arcTo(rect, SkDoubleToScalar(startAngle), SkDoubleToScalar(half), false);
1399         skPath_.arcTo(rect, SkDoubleToScalar(half + startAngle), SkDoubleToScalar(half), false);
1400         skPath_.arcTo(rect, SkDoubleToScalar(half + half + startAngle), SkDoubleToScalar(sweepAngle), false);
1401     } else {
1402         skPath_.arcTo(rect, SkDoubleToScalar(startAngle), SkDoubleToScalar(sweepAngle), false);
1403     }
1404 #else
1405     RSPoint point1(left, top);
1406     RSPoint point2(right, bottom);
1407     if (NearEqual(std::fmod(sweepAngle, FULL_CIRCLE_ANGLE), 0.0) && !NearEqual(startAngle, endAngle)) {
1408         // draw circle
1409         double half = GreatNotEqual(sweepAngle, 0.0) ? HALF_CIRCLE_ANGLE : -HALF_CIRCLE_ANGLE;
1410         path_.ArcTo(point1, point2, static_cast<RSScalar>(startAngle), static_cast<RSScalar>(half));
1411         path_.ArcTo(point1, point2, static_cast<RSScalar>(half + startAngle), static_cast<RSScalar>(half));
1412     } else if (!NearEqual(std::fmod(sweepAngle, FULL_CIRCLE_ANGLE), 0.0) && abs(sweepAngle) > FULL_CIRCLE_ANGLE) {
1413         double half = GreatNotEqual(sweepAngle, 0.0) ? HALF_CIRCLE_ANGLE : -HALF_CIRCLE_ANGLE;
1414         path_.ArcTo(point1, point2, static_cast<RSScalar>(startAngle), static_cast<RSScalar>(half));
1415         path_.ArcTo(point1, point2, static_cast<RSScalar>(half + startAngle), static_cast<RSScalar>(half));
1416         path_.ArcTo(point1, point2, static_cast<RSScalar>(half + half + startAngle), static_cast<RSScalar>(sweepAngle));
1417     } else {
1418         path_.ArcTo(point1, point2, static_cast<RSScalar>(startAngle), static_cast<RSScalar>(sweepAngle));
1419     }
1420 #endif
1421 }
1422 
ClearRect(Rect rect)1423 void RosenRenderOffscreenCanvas::ClearRect(Rect rect)
1424 {
1425 #ifndef USE_ROSEN_DRAWING
1426     SkPaint paint;
1427     paint.setAntiAlias(antiAlias_);
1428     paint.setBlendMode(SkBlendMode::kClear);
1429     auto skRect = SkRect::MakeLTRB(rect.Left(), rect.Top(), rect.Right(), rect.Bottom());
1430     skCanvas_->drawRect(skRect, paint);
1431 #else
1432     RSBrush brush;
1433     brush.SetAntiAlias(antiAlias_);
1434     brush.SetBlendMode(RSBlendMode::CLEAR);
1435     auto drawingRect = RSRect(rect.Left(), rect.Top(), rect.Right(), rect.Bottom());
1436     canvas_->AttachBrush(brush);
1437     canvas_->DrawRect(drawingRect);
1438     canvas_->DetachBrush();
1439 #endif
1440 }
1441 
StrokeRect(Rect rect)1442 void RosenRenderOffscreenCanvas::StrokeRect(Rect rect)
1443 {
1444 #ifndef USE_ROSEN_DRAWING
1445     SkPaint paint = GetStrokePaint();
1446     paint.setAntiAlias(antiAlias_);
1447     SkRect skRect = SkRect::MakeLTRB(rect.Left(), rect.Top(),
1448         rect.Right(), rect.Bottom());
1449     if (HasShadow()) {
1450         SkPath path;
1451         path.addRect(skRect);
1452 #ifndef NEW_SKIA
1453         FlutterDecorationPainter::PaintShadow(path, shadow_, skCanvas_.get());
1454 #else
1455         RosenDecorationPainter::PaintShadow(path, shadow_, skCanvas_.get());
1456 #endif
1457     }
1458     if (strokeState_.GetGradient().IsValid()) {
1459         UpdatePaintShader(paint, strokeState_.GetGradient());
1460     }
1461     if (strokeState_.GetPattern().IsValid()) {
1462         UpdatePaintShader(strokeState_.GetPattern(), paint);
1463     }
1464     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
1465         skCanvas_->drawRect(skRect, paint);
1466     } else {
1467         InitCachePaint();
1468         cacheCanvas_->drawRect(skRect, paint);
1469 #ifndef NEW_SKIA
1470         skCanvas_->drawBitmap(cacheBitmap_, 0, 0, &cachePaint_);
1471 #else
1472         skCanvas_->drawImage(cacheBitmap_.asImage(), 0, 0, SkSamplingOptions(), &cachePaint_);
1473 #endif
1474         cacheBitmap_.eraseColor(0);
1475     }
1476 #else
1477     auto pen = GetStrokePaint();
1478     pen.SetAntiAlias(antiAlias_);
1479     RSRect drawingRect = RSRect(rect.Left(), rect.Top(), rect.Right(), rect.Bottom());
1480     if (HasShadow()) {
1481         RSRecordingPath path;
1482         path.AddRect(drawingRect);
1483         RosenDecorationPainter::PaintShadow(path, shadow_, canvas_.get());
1484     }
1485     if (strokeState_.GetGradient().IsValid()) {
1486         UpdatePaintShader(&pen, nullptr, strokeState_.GetGradient());
1487     }
1488     if (strokeState_.GetPattern().IsValid()) {
1489         UpdatePaintShader(strokeState_.GetPattern(), &pen, nullptr);
1490     }
1491     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
1492         canvas_->AttachPen(pen);
1493         canvas_->DrawRect(drawingRect);
1494         canvas_->DetachPen();
1495     } else {
1496         InitCachePaint();
1497         cacheCanvas_->AttachPen(pen);
1498         cacheCanvas_->DrawRect(drawingRect);
1499         cacheCanvas_->DetachPen();
1500         canvas_->AttachBrush(cacheBrush_);
1501         canvas_->DrawBitmap(cacheBitmap_, 0, 0);
1502         canvas_->DetachBrush();
1503         cacheBitmap_.ClearWithColor(RSColor::COLOR_TRANSPARENT);
1504     }
1505 #endif
1506 }
1507 
Stroke()1508 void RosenRenderOffscreenCanvas::Stroke()
1509 {
1510 #ifndef USE_ROSEN_DRAWING
1511     SkPaint paint = GetStrokePaint();
1512     paint.setAntiAlias(antiAlias_);
1513     if (HasShadow()) {
1514 #ifndef NEW_SKIA
1515         FlutterDecorationPainter::PaintShadow(skPath_, shadow_, skCanvas_.get());
1516 #else
1517         RosenDecorationPainter::PaintShadow(skPath_, shadow_, skCanvas_.get());
1518 #endif
1519     }
1520     if (strokeState_.GetGradient().IsValid()) {
1521         UpdatePaintShader(paint, strokeState_.GetGradient());
1522     }
1523     if (strokeState_.GetPattern().IsValid()) {
1524         UpdatePaintShader(strokeState_.GetPattern(), paint);
1525     }
1526     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
1527         skCanvas_->drawPath(skPath_, paint);
1528     } else {
1529         InitCachePaint();
1530         cacheCanvas_->drawPath(skPath_, paint);
1531 #ifndef NEW_SKIA
1532         skCanvas_->drawBitmap(cacheBitmap_, 0, 0, &cachePaint_);
1533 #else
1534         skCanvas_->drawImage(cacheBitmap_.asImage(), 0, 0, SkSamplingOptions(), &cachePaint_);
1535 #endif
1536         cacheBitmap_.eraseColor(0);
1537     }
1538 #else
1539     auto pen = GetStrokePaint();
1540     pen.SetAntiAlias(antiAlias_);
1541     if (HasShadow()) {
1542         RosenDecorationPainter::PaintShadow(path_, shadow_, canvas_.get());
1543     }
1544     if (strokeState_.GetGradient().IsValid()) {
1545         UpdatePaintShader(&pen, nullptr, strokeState_.GetGradient());
1546     }
1547     if (strokeState_.GetPattern().IsValid()) {
1548         UpdatePaintShader(strokeState_.GetPattern(), &pen, nullptr);
1549     }
1550     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
1551         canvas_->AttachPen(pen);
1552         canvas_->DrawPath(path_);
1553         canvas_->DetachPen();
1554     } else {
1555         InitCachePaint();
1556         cacheCanvas_->AttachPen(pen);
1557         cacheCanvas_->DrawPath(path_);
1558         cacheCanvas_->DetachPen();
1559         canvas_->AttachBrush(cacheBrush_);
1560         canvas_->DrawBitmap(cacheBitmap_, 0, 0);
1561         canvas_->DetachBrush();
1562         cacheBitmap_.ClearWithColor(RSColor::COLOR_TRANSPARENT);
1563     }
1564 #endif
1565 }
1566 
Stroke(const RefPtr<CanvasPath2D> & path)1567 void RosenRenderOffscreenCanvas::Stroke(const RefPtr<CanvasPath2D>& path)
1568 {
1569     if (path == nullptr) {
1570         return;
1571     }
1572     ParsePath2D(path);
1573     Path2DStroke();
1574 #ifndef USE_ROSEN_DRAWING
1575     skPath2d_.reset();
1576 #else
1577     path2d_.Reset();
1578 #endif
1579 }
1580 
1581 #ifndef USE_ROSEN_DRAWING
GetStrokePaint()1582 SkPaint RosenRenderOffscreenCanvas::GetStrokePaint()
1583 {
1584     static const LinearEnumMapNode<LineJoinStyle, SkPaint::Join> skLineJoinTable[] = {
1585         { LineJoinStyle::MITER, SkPaint::Join::kMiter_Join },
1586         { LineJoinStyle::ROUND, SkPaint::Join::kRound_Join },
1587         { LineJoinStyle::BEVEL, SkPaint::Join::kBevel_Join },
1588     };
1589     static const LinearEnumMapNode<LineCapStyle, SkPaint::Cap> skLineCapTable[] = {
1590         { LineCapStyle::BUTT, SkPaint::Cap::kButt_Cap },
1591         { LineCapStyle::ROUND, SkPaint::Cap::kRound_Cap },
1592         { LineCapStyle::SQUARE, SkPaint::Cap::kSquare_Cap },
1593     };
1594     SkPaint paint;
1595     paint.setColor(strokeState_.GetColor().GetValue());
1596     paint.setStyle(SkPaint::Style::kStroke_Style);
1597     paint.setStrokeJoin(ConvertEnumToSkEnum(
1598         strokeState_.GetLineJoin(), skLineJoinTable, ArraySize(skLineJoinTable), SkPaint::Join::kMiter_Join));
1599     paint.setStrokeCap(ConvertEnumToSkEnum(
1600         strokeState_.GetLineCap(), skLineCapTable, ArraySize(skLineCapTable), SkPaint::Cap::kButt_Cap));
1601     paint.setStrokeWidth(static_cast<SkScalar>(strokeState_.GetLineWidth()));
1602     paint.setStrokeMiter(static_cast<SkScalar>(strokeState_.GetMiterLimit()));
1603 
1604     // set line Dash
1605     UpdateLineDash(paint);
1606 
1607     // set global alpha
1608     if (globalState_.HasGlobalAlpha()) {
1609         paint.setAlphaf(globalState_.GetAlpha());
1610     }
1611     return paint;
1612 }
1613 #else
GetStrokePaint()1614 RSPen RosenRenderOffscreenCanvas::GetStrokePaint()
1615 {
1616     static const LinearEnumMapNode<LineJoinStyle, RSPen::JoinStyle> skLineJoinTable[] = {
1617         { LineJoinStyle::MITER, RSPen::JoinStyle::MITER_JOIN },
1618         { LineJoinStyle::ROUND, RSPen::JoinStyle::ROUND_JOIN },
1619         { LineJoinStyle::BEVEL, RSPen::JoinStyle::BEVEL_JOIN },
1620     };
1621     static const LinearEnumMapNode<LineCapStyle, RSPen::CapStyle> skLineCapTable[] = {
1622         { LineCapStyle::BUTT, RSPen::CapStyle::FLAT_CAP },
1623         { LineCapStyle::ROUND, RSPen::CapStyle::ROUND_CAP },
1624         { LineCapStyle::SQUARE, RSPen::CapStyle::SQUARE_CAP },
1625     };
1626     RSPen pen;
1627     pen.SetColor(strokeState_.GetColor().GetValue());
1628     pen.SetJoinStyle(ConvertEnumToDrawingEnum(strokeState_.GetLineJoin(),
1629         skLineJoinTable, ArraySize(skLineJoinTable), RSPen::JoinStyle::MITER_JOIN));
1630     pen.SetCapStyle(ConvertEnumToDrawingEnum(
1631         strokeState_.GetLineCap(), skLineCapTable, ArraySize(skLineCapTable), RSPen::CapStyle::FLAT_CAP));
1632     pen.SetWidth(static_cast<RSScalar>(strokeState_.GetLineWidth()));
1633     pen.SetMiterLimit(static_cast<RSScalar>(strokeState_.GetMiterLimit()));
1634 
1635     // set line Dash
1636     UpdateLineDash(pen);
1637 
1638     // set global alpha
1639     if (globalState_.HasGlobalAlpha()) {
1640         pen.SetAlphaF(globalState_.GetAlpha());
1641     }
1642     return pen;
1643 }
1644 #endif
1645 
SetAntiAlias(bool isEnabled)1646 void RosenRenderOffscreenCanvas::SetAntiAlias(bool isEnabled)
1647 {
1648     antiAlias_ = isEnabled;
1649 }
HasShadow() const1650 bool RosenRenderOffscreenCanvas::HasShadow() const
1651 {
1652     return !(NearZero(shadow_.GetOffset().GetX()) && NearZero(shadow_.GetOffset().GetY()) &&
1653          NearZero(shadow_.GetBlurRadius()));
1654 }
1655 
HasImageShadow() const1656 bool RosenRenderOffscreenCanvas::HasImageShadow() const
1657 {
1658     return !(NearZero(imageShadow_.GetOffset().GetX()) && NearZero(imageShadow_.GetOffset().GetY()) &&
1659          NearZero(imageShadow_.GetBlurRadius()));
1660 }
1661 
Path2DAddPath(const PathArgs & args)1662 void RosenRenderOffscreenCanvas::Path2DAddPath(const PathArgs& args)
1663 {
1664 #ifndef USE_ROSEN_DRAWING
1665     SkPath out;
1666     SkParsePath::FromSVGString(args.cmds.c_str(), &out);
1667     skPath2d_.addPath(out);
1668 #else
1669     RSRecordingPath out;
1670     out.BuildFromSVGString(args.cmds.c_str());
1671     path2d_.AddPath(out);
1672 #endif
1673 }
1674 
Path2DSetTransform(const PathArgs & args)1675 void RosenRenderOffscreenCanvas::Path2DSetTransform(const PathArgs& args)
1676 {
1677 #ifndef USE_ROSEN_DRAWING
1678     SkMatrix skMatrix;
1679     double scaleX = args.para1;
1680     double skewX = args.para2;
1681     double skewY = args.para3;
1682     double scaleY = args.para4;
1683     double translateX = args.para5;
1684     double translateY = args.para6;
1685     skMatrix.setAll(scaleX, skewY, translateX, skewX, scaleY, translateY, 0, 0, 1);
1686     skPath2d_.transform(skMatrix);
1687 #else
1688     RSMatrix matrix;
1689     double scaleX = args.para1;
1690     double skewX = args.para2;
1691     double skewY = args.para3;
1692     double scaleY = args.para4;
1693     double translateX = args.para5;
1694     double translateY = args.para6;
1695     matrix.SetMatrix(scaleX, skewY, translateX, skewX, scaleY, translateY, 0, 0, 1);
1696     path2d_.Transform(matrix);
1697 #endif
1698 }
1699 
Path2DMoveTo(const PathArgs & args)1700 void RosenRenderOffscreenCanvas::Path2DMoveTo(const PathArgs& args)
1701 {
1702     double x = args.para1;
1703     double y = args.para2;
1704 #ifndef USE_ROSEN_DRAWING
1705     skPath2d_.moveTo(x, y);
1706 #else
1707     path2d_.MoveTo(x, y);
1708 #endif
1709 }
1710 
Path2DLineTo(const PathArgs & args)1711 void RosenRenderOffscreenCanvas::Path2DLineTo(const PathArgs& args)
1712 {
1713     double x = args.para1;
1714     double y = args.para2;
1715 #ifndef USE_ROSEN_DRAWING
1716     skPath2d_.lineTo(x, y);
1717 #else
1718     path2d_.LineTo(x, y);
1719 #endif
1720 }
1721 
Path2DArc(const PathArgs & args)1722 void RosenRenderOffscreenCanvas::Path2DArc(const PathArgs& args)
1723 {
1724     double x = args.para1;
1725     double y = args.para2;
1726     double r = args.para3;
1727 #ifndef USE_ROSEN_DRAWING
1728     auto rect = SkRect::MakeLTRB(x - r, y - r,
1729         x + r, y + r);
1730     double startAngle = args.para4 * HALF_CIRCLE_ANGLE / M_PI;
1731     double endAngle = args.para5 * HALF_CIRCLE_ANGLE / M_PI;
1732     double sweepAngle = endAngle - startAngle;
1733     if (!NearZero(args.para6)) {
1734         sweepAngle = endAngle > startAngle ?
1735             (std::fmod(sweepAngle, FULL_CIRCLE_ANGLE) - FULL_CIRCLE_ANGLE) : sweepAngle;
1736     } else {
1737         sweepAngle = endAngle > startAngle ?
1738             sweepAngle : (std::fmod(sweepAngle, FULL_CIRCLE_ANGLE) + FULL_CIRCLE_ANGLE);
1739     }
1740     if (NearEqual(std::fmod(sweepAngle, FULL_CIRCLE_ANGLE), 0.0) && !NearEqual(startAngle, endAngle)) {
1741         skPath2d_.arcTo(rect, startAngle, HALF_CIRCLE_ANGLE, false);
1742         skPath2d_.arcTo(rect, startAngle + HALF_CIRCLE_ANGLE, HALF_CIRCLE_ANGLE, false);
1743     } else if (!NearEqual(std::fmod(sweepAngle, FULL_CIRCLE_ANGLE), 0.0) && abs(sweepAngle) > FULL_CIRCLE_ANGLE) {
1744         skPath2d_.arcTo(rect, startAngle, HALF_CIRCLE_ANGLE, false);
1745         skPath2d_.arcTo(rect, startAngle + HALF_CIRCLE_ANGLE, HALF_CIRCLE_ANGLE, false);
1746         skPath2d_.arcTo(rect, startAngle + HALF_CIRCLE_ANGLE + HALF_CIRCLE_ANGLE, sweepAngle, false);
1747     } else {
1748         skPath2d_.arcTo(rect, startAngle, sweepAngle, false);
1749     }
1750 #else
1751     RSPoint point1(x - r, y - r);
1752     RSPoint point2(x + r, y + r);
1753     double startAngle = args.para4 * HALF_CIRCLE_ANGLE / M_PI;
1754     double endAngle = args.para5 * HALF_CIRCLE_ANGLE / M_PI;
1755     double sweepAngle = endAngle - startAngle;
1756     if (!NearZero(args.para6)) {
1757         sweepAngle = endAngle > startAngle ?
1758             (std::fmod(sweepAngle, FULL_CIRCLE_ANGLE) - FULL_CIRCLE_ANGLE) : sweepAngle;
1759     } else {
1760         sweepAngle = endAngle > startAngle ?
1761             sweepAngle : (std::fmod(sweepAngle, FULL_CIRCLE_ANGLE) + FULL_CIRCLE_ANGLE);
1762     }
1763     if (NearEqual(std::fmod(sweepAngle, FULL_CIRCLE_ANGLE), 0.0) && !NearEqual(startAngle, endAngle)) {
1764         path2d_.ArcTo(point1, point2, startAngle, HALF_CIRCLE_ANGLE);
1765         path2d_.ArcTo(point1, point2, startAngle + HALF_CIRCLE_ANGLE, HALF_CIRCLE_ANGLE);
1766     } else if (!NearEqual(std::fmod(sweepAngle, FULL_CIRCLE_ANGLE), 0.0) && abs(sweepAngle) > FULL_CIRCLE_ANGLE) {
1767         path2d_.ArcTo(point1, point2, startAngle, HALF_CIRCLE_ANGLE);
1768         path2d_.ArcTo(point1, point2, startAngle + HALF_CIRCLE_ANGLE, HALF_CIRCLE_ANGLE);
1769         path2d_.ArcTo(point1, point2, startAngle + HALF_CIRCLE_ANGLE + HALF_CIRCLE_ANGLE, sweepAngle);
1770     } else {
1771         path2d_.ArcTo(point1, point2, startAngle, sweepAngle);
1772     }
1773 #endif
1774 }
1775 
Path2DArcTo(const PathArgs & args)1776 void RosenRenderOffscreenCanvas::Path2DArcTo(const PathArgs& args)
1777 {
1778 #ifndef USE_ROSEN_DRAWING
1779     double x1 = args.para1;
1780     double y1 = args.para2;
1781     double x2 = args.para3;
1782     double y2 = args.para4;
1783     double r = args.para5;
1784     skPath2d_.arcTo(x1, y1, x2, y2, r);
1785 #else
1786     LOGE("Drawing is not supported");
1787 #endif
1788 }
1789 
Path2DQuadraticCurveTo(const PathArgs & args)1790 void RosenRenderOffscreenCanvas::Path2DQuadraticCurveTo(const PathArgs& args)
1791 {
1792     double cpx = args.para1;
1793     double cpy = args.para2;
1794     double x = args.para3;
1795     double y = args.para4;
1796 #ifndef USE_ROSEN_DRAWING
1797     skPath2d_.quadTo(cpx, cpy, x, y);
1798 #else
1799     path2d_.QuadTo(cpx, cpy, x, y);
1800 #endif
1801 }
1802 
Path2DBezierCurveTo(const PathArgs & args)1803 void RosenRenderOffscreenCanvas::Path2DBezierCurveTo(const PathArgs& args)
1804 {
1805     double cp1x = args.para1;
1806     double cp1y = args.para2;
1807     double cp2x = args.para3;
1808     double cp2y = args.para4;
1809     double x = args.para5;
1810     double y = args.para6;
1811 #ifndef USE_ROSEN_DRAWING
1812     skPath2d_.cubicTo(cp1x, cp1y, cp2x, cp2y, x, y);
1813 #else
1814     path2d_.CubicTo(cp1x, cp1y, cp2x, cp2y, x, y);
1815 #endif
1816 }
1817 
Path2DEllipse(const PathArgs & args)1818 void RosenRenderOffscreenCanvas::Path2DEllipse(const PathArgs& args)
1819 {
1820     if (NearEqual(args.para6, args.para7)) {
1821         return; // Just return when startAngle is same as endAngle.
1822     }
1823 
1824     double x = args.para1;
1825     double y = args.para2;
1826     double rx = args.para3;
1827     double ry = args.para4;
1828     double rotation = args.para5 * HALF_CIRCLE_ANGLE / M_PI;
1829     double startAngle = std::fmod(args.para6, M_PI * 2.0);
1830     double endAngle = std::fmod(args.para7, M_PI * 2.0);
1831     bool anticlockwise = NearZero(args.para8) ? false : true;
1832     startAngle = (startAngle < 0.0 ? startAngle + M_PI * 2.0 : startAngle) * HALF_CIRCLE_ANGLE / M_PI;
1833     endAngle = (endAngle < 0.0 ? endAngle + M_PI * 2.0 : endAngle) * HALF_CIRCLE_ANGLE / M_PI;
1834     double sweepAngle = endAngle - startAngle;
1835     if (anticlockwise) {
1836         if (sweepAngle > 0.0) { // Make sure the sweepAngle is negative when anticlockwise.
1837             sweepAngle -= FULL_CIRCLE_ANGLE;
1838         }
1839     } else {
1840         if (sweepAngle < 0.0) { // Make sure the sweepAngle is positive when clockwise.
1841             sweepAngle += FULL_CIRCLE_ANGLE;
1842         }
1843     }
1844 #ifndef USE_ROSEN_DRAWING
1845     auto rect = SkRect::MakeLTRB(x - rx, y - ry,
1846         x + rx, y + ry);
1847 
1848     if (!NearZero(rotation)) {
1849         SkMatrix matrix;
1850         matrix.setRotate(-rotation, x, y);
1851         skPath2d_.transform(matrix);
1852     }
1853     if (NearZero(sweepAngle) && !NearZero(args.para6 - args.para7)) {
1854         // The entire ellipse needs to be drawn with two arcTo.
1855         skPath2d_.arcTo(rect, startAngle, HALF_CIRCLE_ANGLE, false);
1856         skPath2d_.arcTo(rect, startAngle + HALF_CIRCLE_ANGLE, HALF_CIRCLE_ANGLE, false);
1857     } else {
1858         skPath2d_.arcTo(rect, startAngle, sweepAngle, false);
1859     }
1860     if (!NearZero(rotation)) {
1861         SkMatrix matrix;
1862         matrix.setRotate(rotation, x, y);
1863         skPath2d_.transform(matrix);
1864     }
1865 #else
1866     RSPoint point1(x - rx, y - ry);
1867     RSPoint point2(x + rx, y + ry);
1868 
1869     if (!NearZero(rotation)) {
1870         RSMatrix matrix;
1871         matrix.Rotate(-rotation, x, y);
1872         path2d_.Transform(matrix);
1873     }
1874     if (NearZero(sweepAngle) && !NearZero(args.para6 - args.para7)) {
1875         // The entire ellipse needs to be drawn with two arcTo.
1876         path2d_.ArcTo(point1, point2, startAngle, HALF_CIRCLE_ANGLE);
1877         path2d_.ArcTo(point1, point2, startAngle + HALF_CIRCLE_ANGLE, HALF_CIRCLE_ANGLE);
1878     } else {
1879         path2d_.ArcTo(point1, point2, startAngle, sweepAngle);
1880     }
1881     if (!NearZero(rotation)) {
1882         RSMatrix matrix;
1883         matrix.Rotate(rotation, x, y);
1884         path2d_.Transform(matrix);
1885     }
1886 #endif
1887 }
1888 
Path2DRect(const PathArgs & args)1889 void RosenRenderOffscreenCanvas::Path2DRect(const PathArgs& args)
1890 {
1891     double left = args.para1;
1892     double top = args.para2;
1893     double right = args.para3 + args.para1;
1894     double bottom = args.para4 + args.para2;
1895 #ifndef USE_ROSEN_DRAWING
1896     skPath2d_.addRect(SkRect::MakeLTRB(left, top, right, bottom));
1897 #else
1898     path2d_.AddRect(RSRect(left, top, right, bottom));
1899 #endif
1900 }
1901 
Path2DClosePath(const PathArgs & args)1902 void RosenRenderOffscreenCanvas::Path2DClosePath(const PathArgs& args)
1903 {
1904 #ifndef USE_ROSEN_DRAWING
1905     skPath2d_.close();
1906 #else
1907     path2d_.Close();
1908 #endif
1909 }
1910 
Path2DStroke()1911 void RosenRenderOffscreenCanvas::Path2DStroke()
1912 {
1913 #ifndef USE_ROSEN_DRAWING
1914     SkPaint paint = GetStrokePaint();
1915     paint.setAntiAlias(antiAlias_);
1916     if (HasShadow()) {
1917 #ifndef NEW_SKIA
1918         FlutterDecorationPainter::PaintShadow(skPath2d_, shadow_, skCanvas_.get());
1919 #else
1920         RosenDecorationPainter::PaintShadow(skPath2d_, shadow_, skCanvas_.get());
1921 #endif
1922     }
1923     if (strokeState_.GetGradient().IsValid()) {
1924         UpdatePaintShader(paint, strokeState_.GetGradient());
1925     }
1926     if (strokeState_.GetPattern().IsValid()) {
1927         UpdatePaintShader(strokeState_.GetPattern(), paint);
1928     }
1929     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
1930         skCanvas_->drawPath(skPath2d_, paint);
1931     } else {
1932         InitCachePaint();
1933         cacheCanvas_->drawPath(skPath2d_, paint);
1934 #ifndef NEW_SKIA
1935         skCanvas_->drawBitmap(cacheBitmap_, 0, 0, &cachePaint_);
1936 #else
1937         skCanvas_->drawImage(cacheBitmap_.asImage(), 0, 0, SkSamplingOptions(), &cachePaint_);
1938 #endif
1939         cacheBitmap_.eraseColor(0);
1940     }
1941 #else
1942     RSPen pen = GetStrokePaint();
1943     pen.SetAntiAlias(antiAlias_);
1944     if (HasShadow()) {
1945         RosenDecorationPainter::PaintShadow(path2d_, shadow_, canvas_.get());
1946     }
1947     if (strokeState_.GetGradient().IsValid()) {
1948         UpdatePaintShader(&pen, nullptr, strokeState_.GetGradient());
1949     }
1950     if (strokeState_.GetPattern().IsValid()) {
1951         UpdatePaintShader(strokeState_.GetPattern(), &pen, nullptr);
1952     }
1953     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
1954         canvas_->AttachPen(pen);
1955         canvas_->DrawPath(path2d_);
1956         canvas_->DetachPen();
1957     } else {
1958         InitCachePaint();
1959         cacheCanvas_->AttachPen(pen);
1960         cacheCanvas_->DrawPath(path2d_);
1961         cacheCanvas_->DetachPen();
1962         canvas_->AttachBrush(cacheBrush_);
1963         canvas_->DrawBitmap(cacheBitmap_, 0, 0);
1964         canvas_->DetachBrush();
1965         cacheBitmap_.ClearWithColor(RSColor::COLOR_TRANSPARENT);
1966     }
1967 #endif
1968 }
1969 
Path2DFill()1970 void RosenRenderOffscreenCanvas::Path2DFill()
1971 {
1972 #ifndef USE_ROSEN_DRAWING
1973     SkPaint paint;
1974     paint.setAntiAlias(antiAlias_);
1975     paint.setColor(fillState_.GetColor().GetValue());
1976     paint.setStyle(SkPaint::Style::kFill_Style);
1977     if (HasShadow()) {
1978 #ifndef NEW_SKIA
1979         FlutterDecorationPainter::PaintShadow(skPath2d_, shadow_, skCanvas_.get());
1980 #else
1981         RosenDecorationPainter::PaintShadow(skPath2d_, shadow_, skCanvas_.get());
1982 #endif
1983     }
1984     if (fillState_.GetGradient().IsValid()) {
1985         UpdatePaintShader(paint, fillState_.GetGradient());
1986     }
1987     if (fillState_.GetPattern().IsValid()) {
1988         UpdatePaintShader(fillState_.GetPattern(), paint);
1989     }
1990     if (globalState_.HasGlobalAlpha()) {
1991         paint.setAlphaf(globalState_.GetAlpha());
1992     }
1993     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
1994         skCanvas_->drawPath(skPath2d_, paint);
1995     } else {
1996         InitCachePaint();
1997         cacheCanvas_->drawPath(skPath2d_, paint);
1998 #ifndef NEW_SKIA
1999         skCanvas_->drawBitmap(cacheBitmap_, 0, 0, &cachePaint_);
2000 #else
2001         skCanvas_->drawImage(cacheBitmap_.asImage(), 0, 0, SkSamplingOptions(), &cachePaint_);
2002 #endif
2003         cacheBitmap_.eraseColor(0);
2004     }
2005 #else
2006     RSBrush brush;
2007     brush.SetAntiAlias(antiAlias_);
2008     brush.SetColor(fillState_.GetColor().GetValue());
2009     if (HasShadow()) {
2010         RosenDecorationPainter::PaintShadow(path2d_, shadow_, canvas_.get());
2011     }
2012     if (fillState_.GetGradient().IsValid()) {
2013         UpdatePaintShader(nullptr, &brush, fillState_.GetGradient());
2014     }
2015     if (fillState_.GetPattern().IsValid()) {
2016         UpdatePaintShader(fillState_.GetPattern(), nullptr, &brush);
2017     }
2018     if (globalState_.HasGlobalAlpha()) {
2019         brush.SetAlphaF(globalState_.GetAlpha());
2020     }
2021     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
2022         canvas_->AttachBrush(brush);
2023         canvas_->DrawPath(path2d_);
2024         canvas_->DetachBrush();
2025     } else {
2026         InitCachePaint();
2027         cacheCanvas_->AttachBrush(brush);
2028         cacheCanvas_->DrawPath(path2d_);
2029         cacheCanvas_->DetachBrush();
2030         canvas_->AttachBrush(cacheBrush_);
2031         canvas_->DrawBitmap(cacheBitmap_, 0, 0);
2032         canvas_->DetachBrush();
2033         cacheBitmap_.ClearWithColor(RSColor::COLOR_TRANSPARENT);
2034     }
2035 #endif
2036 }
2037 
Path2DClip()2038 void RosenRenderOffscreenCanvas::Path2DClip()
2039 {
2040 #ifndef USE_ROSEN_DRAWING
2041     skCanvas_->clipPath(skPath2d_);
2042 #else
2043     canvas_->ClipPath(path2d_, RSClipOp::INTERSECT);
2044 #endif
2045 }
2046 
2047 #ifndef USE_ROSEN_DRAWING
UpdateLineDash(SkPaint & paint)2048 void RosenRenderOffscreenCanvas::UpdateLineDash(SkPaint& paint)
2049 {
2050     if (!strokeState_.GetLineDash().lineDash.empty()) {
2051         auto lineDashState = strokeState_.GetLineDash().lineDash;
2052         SkScalar intervals[lineDashState.size()];
2053         for (size_t i = 0; i < lineDashState.size(); ++i) {
2054             intervals[i] = SkDoubleToScalar(lineDashState[i]);
2055         }
2056         SkScalar phase = SkDoubleToScalar(strokeState_.GetLineDash().dashOffset);
2057         paint.setPathEffect(SkDashPathEffect::Make(intervals, lineDashState.size(), phase));
2058     }
2059 }
2060 #else
UpdateLineDash(RSPen & pen)2061 void RosenRenderOffscreenCanvas::UpdateLineDash(RSPen& pen)
2062 {
2063     if (!strokeState_.GetLineDash().lineDash.empty()) {
2064         auto lineDashState = strokeState_.GetLineDash().lineDash;
2065         RSScalar intervals[lineDashState.size()];
2066         for (size_t i = 0; i < lineDashState.size(); ++i) {
2067             intervals[i] = static_cast<RSScalar>(lineDashState[i]);
2068         }
2069         RSScalar phase = static_cast<RSScalar>(strokeState_.GetLineDash().dashOffset);
2070         pen.SetPathEffect(RSPathEffect::CreateDashPathEffect(intervals, lineDashState.size(), phase));
2071     }
2072 }
2073 #endif
2074 
ArcTo(const ArcToParam & param)2075 void RosenRenderOffscreenCanvas::ArcTo(const ArcToParam& param)
2076 {
2077 #ifndef USE_ROSEN_DRAWING
2078     double x1 = param.x1;
2079     double y1 = param.y1;
2080     double x2 = param.x2;
2081     double y2 = param.y2;
2082     double radius = param.radius;
2083     skPath_.arcTo(SkDoubleToScalar(x1), SkDoubleToScalar(y1), SkDoubleToScalar(x2), SkDoubleToScalar(y2),
2084         SkDoubleToScalar(radius));
2085 #else
2086     LOGE("Drawing is not supported");
2087 #endif
2088 }
MoveTo(double x,double y)2089 void RosenRenderOffscreenCanvas::MoveTo(double x, double y)
2090 {
2091 #ifndef USE_ROSEN_DRAWING
2092     skPath_.moveTo(SkDoubleToScalar(x), SkDoubleToScalar(y));
2093 #else
2094     path_.MoveTo(static_cast<RSScalar>(x), static_cast<RSScalar>(y));
2095 #endif
2096 }
ClosePath()2097 void RosenRenderOffscreenCanvas::ClosePath()
2098 {
2099 #ifndef USE_ROSEN_DRAWING
2100     skPath_.close();
2101 #else
2102     path_.Close();
2103 #endif
2104 }
2105 
Rotate(double angle)2106 void RosenRenderOffscreenCanvas::Rotate(double angle)
2107 {
2108 #ifndef USE_ROSEN_DRAWING
2109     skCanvas_->rotate(angle * 180 / M_PI);
2110 #else
2111     canvas_->Rotate(angle * 180 / M_PI);
2112 #endif
2113 }
Scale(double x,double y)2114 void RosenRenderOffscreenCanvas::Scale(double x, double y)
2115 {
2116 #ifndef USE_ROSEN_DRAWING
2117     skCanvas_->scale(x, y);
2118 #else
2119     canvas_->Scale(x, y);
2120 #endif
2121 }
2122 
FillText(const std::string & text,double x,double y,const PaintState & state)2123 void RosenRenderOffscreenCanvas::FillText(const std::string& text, double x, double y, const PaintState& state)
2124 {
2125     if (!UpdateOffParagraph(text, false, state, HasShadow())) {
2126         return;
2127     }
2128     PaintText(text, x, y, false, HasShadow());
2129 }
2130 
StrokeText(const std::string & text,double x,double y,const PaintState & state)2131 void RosenRenderOffscreenCanvas::StrokeText(const std::string& text, double x, double y, const PaintState& state)
2132 {
2133     if (HasShadow()) {
2134         if (!UpdateOffParagraph(text, true, state, true)) {
2135             return;
2136         }
2137         PaintText(text, x, y, true, true);
2138     }
2139 
2140     if (!UpdateOffParagraph(text, true, state)) {
2141         return;
2142     }
2143     PaintText(text, x, y, true);
2144 }
2145 
MeasureText(const std::string & text,const PaintState & state)2146 double RosenRenderOffscreenCanvas::MeasureText(const std::string& text, const PaintState& state)
2147 {
2148     using namespace Constants;
2149     txt::ParagraphStyle style;
2150     style.text_align = ConvertTxtTextAlign(state.GetTextAlign());
2151     style.text_direction = ConvertTxtTextDirection(state.GetOffTextDirection());
2152 #ifndef USE_ROSEN_DRAWING
2153 #ifndef NEW_SKIA
2154     auto fontCollection = FlutterFontCollection::GetInstance().GetFontCollection();
2155 #else
2156     auto fontCollection = RosenFontCollection::GetInstance().GetFontCollection();
2157 #endif
2158 #else
2159     auto fontCollection = RosenFontCollection::GetInstance().GetFontCollection();
2160 #endif
2161     if (!fontCollection) {
2162         LOGW("MeasureText: fontCollection is null");
2163         return 0.0;
2164     }
2165     std::unique_ptr<txt::ParagraphBuilder> builder = txt::ParagraphBuilder::CreateTxtBuilder(style, fontCollection);
2166     txt::TextStyle txtStyle;
2167     ConvertTxtStyle(state.GetTextStyle(), pipelineContext_, txtStyle);
2168     txtStyle.font_size = state.GetTextStyle().GetFontSize().Value();
2169     builder->PushStyle(txtStyle);
2170     builder->AddText(StringUtils::Str8ToStr16(text));
2171     auto paragraph = builder->Build();
2172     paragraph->Layout(Size::INFINITE_SIZE);
2173     return paragraph->GetMaxIntrinsicWidth();
2174 }
2175 
MeasureTextHeight(const std::string & text,const PaintState & state)2176 double RosenRenderOffscreenCanvas::MeasureTextHeight(const std::string& text, const PaintState& state)
2177 {
2178     using namespace Constants;
2179     txt::ParagraphStyle style;
2180     style.text_align = ConvertTxtTextAlign(state.GetTextAlign());
2181     style.text_direction = ConvertTxtTextDirection(state.GetOffTextDirection());
2182 #ifndef USE_ROSEN_DRAWING
2183 #ifndef NEW_SKIA
2184     auto fontCollection = FlutterFontCollection::GetInstance().GetFontCollection();
2185 #else
2186     auto fontCollection = RosenFontCollection::GetInstance().GetFontCollection();
2187 #endif
2188 #else
2189     auto fontCollection = RosenFontCollection::GetInstance().GetFontCollection();
2190 #endif
2191     if (!fontCollection) {
2192         LOGW("MeasureText: fontCollection is null");
2193         return 0.0;
2194     }
2195     std::unique_ptr<txt::ParagraphBuilder> builder = txt::ParagraphBuilder::CreateTxtBuilder(style, fontCollection);
2196     txt::TextStyle txtStyle;
2197     ConvertTxtStyle(state.GetTextStyle(), pipelineContext_, txtStyle);
2198     txtStyle.font_size = state.GetTextStyle().GetFontSize().Value();
2199     builder->PushStyle(txtStyle);
2200     builder->AddText(StringUtils::Str8ToStr16(text));
2201     auto paragraph = builder->Build();
2202     paragraph->Layout(Size::INFINITE_SIZE);
2203     return paragraph->GetHeight();
2204 }
2205 
MeasureTextMetrics(const std::string & text,const PaintState & state)2206 TextMetrics RosenRenderOffscreenCanvas::MeasureTextMetrics(const std::string& text, const PaintState& state)
2207 {
2208     using namespace Constants;
2209     txt::ParagraphStyle style;
2210     style.text_align = ConvertTxtTextAlign(state.GetTextAlign());
2211     style.text_direction = ConvertTxtTextDirection(state.GetOffTextDirection());
2212 #ifndef USE_ROSEN_DRAWING
2213 #ifndef NEW_SKIA
2214     auto fontCollection = FlutterFontCollection::GetInstance().GetFontCollection();
2215 #else
2216     auto fontCollection = RosenFontCollection::GetInstance().GetFontCollection();
2217 #endif
2218 #else
2219     auto fontCollection = RosenFontCollection::GetInstance().GetFontCollection();
2220 #endif
2221     if (!fontCollection) {
2222         LOGW("MeasureText: fontCollection is null");
2223         return { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
2224     }
2225     std::unique_ptr<txt::ParagraphBuilder> builder = txt::ParagraphBuilder::CreateTxtBuilder(style, fontCollection);
2226     txt::TextStyle txtStyle;
2227     ConvertTxtStyle(state.GetTextStyle(), pipelineContext_, txtStyle);
2228     txtStyle.font_size = state.GetTextStyle().GetFontSize().Value();
2229     builder->PushStyle(txtStyle);
2230     builder->AddText(StringUtils::Str8ToStr16(text));
2231     auto paragraph = builder->Build();
2232     paragraph->Layout(Size::INFINITE_SIZE);
2233 
2234     auto textAlign = state.GetTextAlign();
2235     auto textBaseLine = state.GetTextStyle().GetTextBaseline();
2236 
2237     auto width = paragraph->GetMaxIntrinsicWidth();
2238     auto height = paragraph->GetHeight();
2239 
2240     auto actualBoundingBoxLeft = -GetAlignOffset(text, textAlign, paragraph);
2241     auto actualBoundingBoxRight = width - actualBoundingBoxLeft;
2242     auto actualBoundingBoxAscent = -GetBaselineOffset(textBaseLine, paragraph);
2243     auto actualBoundingBoxDescent = height - actualBoundingBoxAscent;
2244 
2245     return { width, height, actualBoundingBoxLeft, actualBoundingBoxRight, actualBoundingBoxAscent,
2246         actualBoundingBoxDescent };
2247 }
2248 
PaintText(const std::string & text,double x,double y,bool isStroke,bool hasShadow)2249 void RosenRenderOffscreenCanvas::PaintText(const std::string& text, double x, double y, bool isStroke, bool hasShadow)
2250 {
2251     paragraph_->Layout(width_);
2252     if (width_ > paragraph_->GetMaxIntrinsicWidth()) {
2253         paragraph_->Layout(std::ceil(paragraph_->GetMaxIntrinsicWidth()));
2254     }
2255 #ifndef USE_ROSEN_DRAWING
2256     auto align = isStroke ? strokeState_.GetTextAlign() : fillState_.GetTextAlign();
2257     double dx = x + GetAlignOffset(text, align, paragraph_);
2258     auto baseline =
2259         isStroke ? strokeState_.GetTextStyle().GetTextBaseline() : fillState_.GetTextStyle().GetTextBaseline();
2260     double dy = y + GetBaselineOffset(baseline, paragraph_);
2261 
2262     if (hasShadow) {
2263         skCanvas_->save();
2264         auto shadowOffsetX = shadow_.GetOffset().GetX();
2265         auto shadowOffsetY = shadow_.GetOffset().GetY();
2266         paragraph_->Paint(skCanvas_.get(), dx + shadowOffsetX, dy + shadowOffsetY);
2267         skCanvas_->restore();
2268         return;
2269     }
2270     paragraph_->Paint(skCanvas_.get(), dx, dy);
2271 #else
2272     if (hasShadow) {
2273         canvas_->Save();
2274         LOGE("Drawing is not supported");
2275         canvas_->Restore();
2276         return;
2277     }
2278     LOGE("Drawing is not supported");
2279 #endif
2280 }
2281 
GetAlignOffset(const std::string & text,TextAlign align,std::unique_ptr<txt::Paragraph> & paragraph)2282 double RosenRenderOffscreenCanvas::GetAlignOffset(const std::string& text, TextAlign align,
2283     std::unique_ptr<txt::Paragraph>& paragraph)
2284 {
2285     double x = 0.0;
2286     switch (align) {
2287         case TextAlign::LEFT:
2288             x = 0.0;
2289             break;
2290         case TextAlign::START:
2291             x = (GetTextDirection(text) == TextDirection::LTR) ? 0.0 : -paragraph->GetMaxIntrinsicWidth();
2292             break;
2293         case TextAlign::RIGHT:
2294             x = -paragraph->GetMaxIntrinsicWidth();
2295             break;
2296         case TextAlign::END:
2297             x = (GetTextDirection(text) == TextDirection::LTR) ? -paragraph->GetMaxIntrinsicWidth() : 0.0;
2298             break;
2299         case TextAlign::CENTER:
2300             x = -paragraph->GetMaxIntrinsicWidth() / 2;
2301             break;
2302         default:
2303             x = 0.0;
2304             break;
2305     }
2306     return x;
2307 }
2308 
GetTextDirection(const std::string & text)2309 TextDirection RosenRenderOffscreenCanvas::GetTextDirection(const std::string& text)
2310 {
2311     auto wstring = StringUtils::ToWstring(text);
2312     // Find first strong direction char.
2313     for (const auto& charInStr : wstring) {
2314         auto direction = u_charDirection(charInStr);
2315         if (direction == UCharDirection::U_LEFT_TO_RIGHT) {
2316             return TextDirection::LTR;
2317         }
2318         if (direction == UCharDirection::U_RIGHT_TO_LEFT || direction == UCharDirection::U_RIGHT_TO_LEFT_ARABIC) {
2319             return TextDirection::RTL;
2320         }
2321     }
2322     return TextDirection::INHERIT;
2323 }
2324 
InitCachePaint()2325 void RosenRenderOffscreenCanvas::InitCachePaint()
2326 {
2327 #ifndef USE_ROSEN_DRAWING
2328     cachePaint_.setBlendMode(
2329         ConvertEnumToSkEnum(globalState_.GetType(), SK_BLEND_MODE_TABLE, BLEND_MODE_SIZE, SkBlendMode::kSrcOver));
2330 #else
2331     cacheBrush_.SetBlendMode(ConvertEnumToDrawingEnum(
2332         globalState_.GetType(), DRAWING_BLEND_MODE_TABLE, BLEND_MODE_SIZE, RSBlendMode::SRC_OVER));
2333 #endif
2334 }
2335 
UpdateOffParagraph(const std::string & text,bool isStroke,const PaintState & state,bool hasShadow)2336 bool RosenRenderOffscreenCanvas::UpdateOffParagraph(const std::string& text, bool isStroke,
2337     const PaintState& state, bool hasShadow)
2338 {
2339     using namespace Constants;
2340     txt::ParagraphStyle style;
2341     if (isStroke) {
2342         style.text_align = ConvertTxtTextAlign(strokeState_.GetTextAlign());
2343     } else {
2344         style.text_align = ConvertTxtTextAlign(fillState_.GetTextAlign());
2345     }
2346     style.text_direction = ConvertTxtTextDirection(state.GetOffTextDirection());
2347 #ifndef USE_ROSEN_DRAWING
2348 #ifndef NEW_SKIA
2349     auto fontCollection = FlutterFontCollection::GetInstance().GetFontCollection();
2350 #else
2351     auto fontCollection = RosenFontCollection::GetInstance().GetFontCollection();
2352 #endif
2353 #else
2354     auto fontCollection = RosenFontCollection::GetInstance().GetFontCollection();
2355 #endif
2356     if (!fontCollection) {
2357         return false;
2358     }
2359     std::unique_ptr<txt::ParagraphBuilder> builder = txt::ParagraphBuilder::CreateTxtBuilder(style, fontCollection);
2360     txt::TextStyle txtStyle;
2361     if (!isStroke && hasShadow) {
2362         txt::TextShadow txtShadow;
2363         txtShadow.color = shadow_.GetColor().GetValue();
2364         txtShadow.offset.fX = shadow_.GetOffset().GetX();
2365         txtShadow.offset.fY = shadow_.GetOffset().GetY();
2366 #ifndef NEW_SKIA
2367         txtShadow.blur_radius = shadow_.GetBlurRadius();
2368 #else
2369         txtShadow.blur_sigma = shadow_.GetBlurRadius();
2370 #endif
2371         txtStyle.text_shadows.emplace_back(txtShadow);
2372     }
2373     txtStyle.locale = Localization::GetInstance()->GetFontLocale();
2374     UpdateTextStyleForeground(isStroke, txtStyle, hasShadow);
2375     builder->PushStyle(txtStyle);
2376     builder->AddText(StringUtils::Str8ToStr16(text));
2377     paragraph_ = builder->Build();
2378     return true;
2379 }
2380 
UpdateTextStyleForeground(bool isStroke,txt::TextStyle & txtStyle,bool hasShadow)2381 void RosenRenderOffscreenCanvas::UpdateTextStyleForeground(
2382     bool isStroke, txt::TextStyle& txtStyle, bool hasShadow)
2383 {
2384     using namespace Constants;
2385 #ifndef USE_ROSEN_DRAWING
2386     if (!isStroke) {
2387         txtStyle.color = ConvertSkColor(fillState_.GetColor());
2388         txtStyle.font_size = fillState_.GetTextStyle().GetFontSize().Value();
2389         ConvertTxtStyle(fillState_.GetTextStyle(), pipelineContext_, txtStyle);
2390         if (fillState_.GetGradient().IsValid()) {
2391             SkPaint paint;
2392             paint.setStyle(SkPaint::Style::kFill_Style);
2393             UpdatePaintShader(paint, fillState_.GetGradient());
2394             txtStyle.foreground = paint;
2395             txtStyle.has_foreground = true;
2396         }
2397         if (globalState_.HasGlobalAlpha()) {
2398             if (txtStyle.has_foreground) {
2399                 txtStyle.foreground.setColor(fillState_.GetColor().GetValue());
2400                 txtStyle.foreground.setAlphaf(globalState_.GetAlpha()); // set alpha after color
2401             } else {
2402                 SkPaint paint;
2403                 paint.setColor(fillState_.GetColor().GetValue());
2404                 paint.setAlphaf(globalState_.GetAlpha()); // set alpha after color
2405                 txtStyle.foreground = paint;
2406                 txtStyle.has_foreground = true;
2407             }
2408         }
2409     } else {
2410         // use foreground to draw stroke
2411         SkPaint paint = GetStrokePaint();
2412         ConvertTxtStyle(strokeState_.GetTextStyle(), pipelineContext_, txtStyle);
2413         txtStyle.font_size = strokeState_.GetTextStyle().GetFontSize().Value();
2414         if (strokeState_.GetGradient().IsValid()) {
2415             UpdatePaintShader(paint, strokeState_.GetGradient());
2416         }
2417         if (hasShadow) {
2418             paint.setColor(shadow_.GetColor().GetValue());
2419 #ifndef NEW_SKIA
2420             paint.setMaskFilter(SkMaskFilter::MakeBlur(SkBlurStyle::kNormal_SkBlurStyle,
2421                 FlutterDecorationPainter::ConvertRadiusToSigma(shadow_.GetBlurRadius())));
2422 #else
2423             paint.setMaskFilter(SkMaskFilter::MakeBlur(SkBlurStyle::kNormal_SkBlurStyle,
2424                 RosenDecorationPainter::ConvertRadiusToSigma(shadow_.GetBlurRadius())));
2425 #endif
2426         }
2427         txtStyle.foreground = paint;
2428         txtStyle.has_foreground = true;
2429     }
2430 #else
2431     LOGE("Drawing is not supported");
2432 #endif
2433 }
2434 
GetBaselineOffset(TextBaseline baseline,std::unique_ptr<txt::Paragraph> & paragraph)2435 double RosenRenderOffscreenCanvas::GetBaselineOffset(TextBaseline baseline,
2436     std::unique_ptr<txt::Paragraph>& paragraph)
2437 {
2438     double y = 0.0;
2439     switch (baseline) {
2440         case TextBaseline::ALPHABETIC:
2441             y = -paragraph->GetAlphabeticBaseline();
2442             break;
2443         case TextBaseline::IDEOGRAPHIC:
2444             y = -paragraph->GetIdeographicBaseline();
2445             break;
2446         case TextBaseline::BOTTOM:
2447             y = -paragraph->GetHeight();
2448             break;
2449         case TextBaseline::TOP:
2450             y = 0.0;
2451             break;
2452         case TextBaseline::MIDDLE:
2453             y = -paragraph->GetHeight() / 2;
2454             break;
2455         case TextBaseline::HANGING:
2456             y = -HANGING_PERCENT * (paragraph->GetHeight() - paragraph->GetAlphabeticBaseline());
2457             break;
2458         default:
2459             y = -paragraph->GetAlphabeticBaseline();
2460             break;
2461     }
2462     return y;
2463 }
LineTo(double x,double y)2464 void RosenRenderOffscreenCanvas::LineTo(double x, double y)
2465 {
2466 #ifndef USE_ROSEN_DRAWING
2467     skPath_.lineTo(SkDoubleToScalar(x), SkDoubleToScalar(y));
2468 #else
2469     path_.LineTo(static_cast<RSScalar>(x), static_cast<RSScalar>(y));
2470 #endif
2471 }
BezierCurveTo(const BezierCurveParam & param)2472 void RosenRenderOffscreenCanvas::BezierCurveTo(const BezierCurveParam& param)
2473 {
2474 #ifndef USE_ROSEN_DRAWING
2475     skPath_.cubicTo(SkDoubleToScalar(param.cp1x), SkDoubleToScalar(param.cp1y),
2476         SkDoubleToScalar(param.cp2x), SkDoubleToScalar(param.cp2y),
2477         SkDoubleToScalar(param.x), SkDoubleToScalar(param.y));
2478 #else
2479     path_.CubicTo(static_cast<RSScalar>(param.cp1x), static_cast<RSScalar>(param.cp1y),
2480         static_cast<RSScalar>(param.cp2x), static_cast<RSScalar>(param.cp2y),
2481         static_cast<RSScalar>(param.x), static_cast<RSScalar>(param.y));
2482 #endif
2483 }
QuadraticCurveTo(const QuadraticCurveParam & param)2484 void RosenRenderOffscreenCanvas::QuadraticCurveTo(const QuadraticCurveParam& param)
2485 {
2486 #ifndef USE_ROSEN_DRAWING
2487     skPath_.quadTo(SkDoubleToScalar(param.cpx), SkDoubleToScalar(param.cpy),
2488         SkDoubleToScalar(param.x), SkDoubleToScalar(param.y));
2489 #else
2490     path_.QuadTo(static_cast<RSScalar>(param.cpx), static_cast<RSScalar>(param.cpy),
2491         static_cast<RSScalar>(param.x), static_cast<RSScalar>(param.y));
2492 #endif
2493 }
Ellipse(const EllipseParam & param)2494 void RosenRenderOffscreenCanvas::Ellipse(const EllipseParam& param)
2495 {
2496     // Init the start and end angle, then calculated the sweepAngle.
2497     double startAngle = std::fmod(param.startAngle, M_PI * 2.0);
2498     double endAngle = std::fmod(param.endAngle, M_PI * 2.0);
2499     startAngle = (startAngle < 0.0 ? startAngle + M_PI * 2.0 : startAngle) * HALF_CIRCLE_ANGLE / M_PI;
2500     endAngle = (endAngle < 0.0 ? endAngle + M_PI * 2.0 : endAngle) * HALF_CIRCLE_ANGLE / M_PI;
2501     if (NearEqual(param.startAngle, param.endAngle)) {
2502         return; // Just return when startAngle is same as endAngle.
2503     }
2504     double rotation = param.rotation * HALF_CIRCLE_ANGLE / M_PI;
2505     double sweepAngle = endAngle - startAngle;
2506     if (param.anticlockwise) {
2507         if (sweepAngle > 0.0) { // Make sure the sweepAngle is negative when anticlockwise.
2508             sweepAngle -= FULL_CIRCLE_ANGLE;
2509         }
2510     } else {
2511         if (sweepAngle < 0.0) { // Make sure the sweepAngle is positive when clockwise.
2512             sweepAngle += FULL_CIRCLE_ANGLE;
2513         }
2514     }
2515 
2516     // Init the oval Rect(left, top, right, bottom).
2517     double left = param.x - param.radiusX;
2518     double top = param.y - param.radiusY;
2519     double right = param.x + param.radiusX;
2520     double bottom = param.y + param.radiusY;
2521 #ifndef USE_ROSEN_DRAWING
2522     auto rect = SkRect::MakeLTRB(left, top, right, bottom);
2523     if (!NearZero(rotation)) {
2524         SkMatrix matrix;
2525         matrix.setRotate(-rotation, param.x, param.y);
2526         skPath_.transform(matrix);
2527     }
2528     if (NearZero(sweepAngle) && !NearZero(param.endAngle - param.startAngle)) {
2529         // The entire ellipse needs to be drawn with two arcTo.
2530         skPath_.arcTo(rect, startAngle, HALF_CIRCLE_ANGLE, false);
2531         skPath_.arcTo(rect, startAngle + HALF_CIRCLE_ANGLE, HALF_CIRCLE_ANGLE, false);
2532     } else {
2533         skPath_.arcTo(rect, startAngle, sweepAngle, false);
2534     }
2535     if (!NearZero(rotation)) {
2536         SkMatrix matrix;
2537         matrix.setRotate(rotation, param.x, param.y);
2538         skPath_.transform(matrix);
2539     }
2540 #else
2541     RSPoint point1(left, top);
2542     RSPoint point2(right, bottom);
2543     if (!NearZero(rotation)) {
2544         RSMatrix matrix;
2545         matrix.Rotate(-rotation, param.x, param.y);
2546         path_.Transform(matrix);
2547     }
2548     if (NearZero(sweepAngle) && !NearZero(param.endAngle - param.startAngle)) {
2549         // The entire ellipse needs to be drawn with two arcTo.
2550         path_.ArcTo(point1, point2, startAngle, HALF_CIRCLE_ANGLE);
2551         path_.ArcTo(point1, point2, startAngle + HALF_CIRCLE_ANGLE, HALF_CIRCLE_ANGLE);
2552     } else {
2553         path_.ArcTo(point1, point2, startAngle, sweepAngle);
2554     }
2555     if (!NearZero(rotation)) {
2556         RSMatrix matrix;
2557         matrix.Rotate(rotation, param.x, param.y);
2558         path_.Transform(matrix);
2559     }
2560 #endif
2561 }
SetTransform(const TransformParam & param)2562 void RosenRenderOffscreenCanvas::SetTransform(const TransformParam& param)
2563 {
2564     auto pipeline = pipelineContext_.Upgrade();
2565     if (!pipeline) {
2566         return;
2567     }
2568 
2569     // use physical pixel to store bitmap
2570     double viewScale = pipeline->GetViewScale();
2571 
2572 #ifndef USE_ROSEN_DRAWING
2573     SkMatrix skMatrix;
2574     skMatrix.setAll(param.scaleX * viewScale, param.skewY * viewScale, param.translateX, param.skewX * viewScale,
2575         param.scaleY * viewScale, param.translateY, 0, 0, 1);
2576     skCanvas_->setMatrix(skMatrix);
2577 #else
2578     RSMatrix matrix;
2579     matrix.SetMatrix(param.scaleX * viewScale, param.skewY * viewScale, param.translateX, param.skewX * viewScale,
2580         param.scaleY * viewScale, param.translateY, 0, 0, 1);
2581     canvas_->SetMatrix(matrix);
2582 #endif
2583 }
Transform(const TransformParam & param)2584 void RosenRenderOffscreenCanvas::Transform(const TransformParam& param)
2585 {
2586 #ifndef USE_ROSEN_DRAWING
2587     SkMatrix skMatrix;
2588     skMatrix.setAll(param.scaleX, param.skewY, param.translateX, param.skewX, param.scaleY, param.translateY, 0, 0, 1);
2589     skCanvas_->concat(skMatrix);
2590 #else
2591     RSMatrix matrix;
2592     matrix.SetMatrix(param.scaleX, param.skewY, param.translateX, param.skewX, param.scaleY, param.translateY, 0, 0, 1);
2593     canvas_->ConcatMatrix(matrix);
2594 #endif
2595 }
Translate(double x,double y)2596 void RosenRenderOffscreenCanvas::Translate(double x, double y)
2597 {
2598 #ifndef USE_ROSEN_DRAWING
2599     skCanvas_->translate(x, y);
2600 #else
2601     canvas_->Translate(x, y);
2602 #endif
2603 }
2604 
TranspareCmdToPath(const RefPtr<CanvasPath2D> & path)2605 void RosenRenderOffscreenCanvas::TranspareCmdToPath(const RefPtr<CanvasPath2D>& path)
2606 {
2607 #ifndef USE_ROSEN_DRAWING
2608     skPath2d_.reset();
2609 #else
2610     path2d_.Reset();
2611 #endif
2612     for (const auto& [cmd, args] : path->GetCaches()) {
2613         switch (cmd) {
2614             case PathCmd::CMDS: {
2615                 Path2DAddPath(args);
2616                 break;
2617             }
2618             case PathCmd::TRANSFORM: {
2619                 Path2DSetTransform(args);
2620                 break;
2621             }
2622             case PathCmd::MOVE_TO: {
2623                 Path2DMoveTo(args);
2624                 break;
2625             }
2626             case PathCmd::LINE_TO: {
2627                 Path2DLineTo(args);
2628                 break;
2629             }
2630             case PathCmd::ARC: {
2631                 Path2DArc(args);
2632                 break;
2633             }
2634             case PathCmd::ARC_TO: {
2635                 Path2DArcTo(args);
2636                 break;
2637             }
2638             case PathCmd::QUADRATIC_CURVE_TO: {
2639                 Path2DQuadraticCurveTo(args);
2640                 break;
2641             }
2642             case PathCmd::BEZIER_CURVE_TO: {
2643                 Path2DBezierCurveTo(args);
2644                 break;
2645             }
2646             case PathCmd::ELLIPSE: {
2647                 Path2DEllipse(args);
2648                 break;
2649             }
2650             case PathCmd::RECT: {
2651                 Path2DRect(args);
2652                 break;
2653             }
2654             case PathCmd::CLOSE_PATH: {
2655                 Path2DClosePath(args);
2656                 break;
2657             }
2658             default: {
2659                 break;
2660             }
2661         }
2662     }
2663 }
2664 
2665 #ifndef USE_ROSEN_DRAWING
IsPointInPathByColor(double x,double y,SkPath & path,SkColor colorMatch)2666 bool RosenRenderOffscreenCanvas::IsPointInPathByColor(double x, double y, SkPath& path, SkColor colorMatch)
2667 {
2668     auto imageInfo = SkImageInfo::Make(width_, height_, SkColorType::kRGBA_8888_SkColorType,
2669         SkAlphaType::kOpaque_SkAlphaType);
2670     SkBitmap skBitmap;
2671     skBitmap.allocPixels(imageInfo);
2672     std::unique_ptr<SkCanvas> skCanvas = std::make_unique<SkCanvas>(skBitmap);
2673 
2674     SkPaint paint;
2675     paint.setColor(SK_ColorRED);
2676     paint.setStyle(SkPaint::Style::kFill_Style);
2677     skCanvas->drawPath(path, paint);
2678 
2679     paint.setColor(SK_ColorBLUE);
2680     paint.setStyle(SkPaint::Style::kStroke_Style);
2681     paint.setStrokeWidth(static_cast<SkScalar>(strokeState_.GetLineWidth()));
2682     skCanvas->drawPath(path, paint);
2683 
2684     SkColor color = skBitmap.getColor(x, y);
2685     if (color == colorMatch) {
2686         return true;
2687     }
2688     return false;
2689 }
2690 #else
IsPointInPathByColor(double x,double y,RSPath & path,RSColorQuad colorMatch)2691 bool RosenRenderOffscreenCanvas::IsPointInPathByColor(
2692     double x, double y, RSPath& path, RSColorQuad colorMatch)
2693 {
2694     RSBitmapFormat format { RSColorType::COLORTYPE_RGBA_8888,
2695         RSAlphaType::ALPHATYPE_OPAQUE };
2696 
2697     RSBitmap bitmap;
2698     bitmap.Build(width_, height_, format);
2699     std::unique_ptr<RSCanvas> canvas = std::make_unique<RSCanvas>();
2700     canvas->Bind(bitmap);
2701 
2702     RSBrush brush;
2703     brush.SetColor(RSColor::COLOR_RED);
2704     canvas->AttachBrush(brush);
2705     canvas->DrawPath(path);
2706     canvas->DetachBrush();
2707 
2708     RSPen pen;
2709     pen.SetColor(RSColor::COLOR_BLUE);
2710     pen.SetWidth(static_cast<RSScalar>(strokeState_.GetLineWidth()));
2711     canvas->AttachPen(pen);
2712     canvas->DrawPath(path);
2713     canvas->DetachPen();
2714 
2715     RSColorQuad color = bitmap.GetColor(x, y);
2716     if (color == colorMatch) {
2717         return true;
2718     }
2719     return false;
2720 }
2721 #endif
2722 
IsPointInPath(double x,double y)2723 bool RosenRenderOffscreenCanvas::IsPointInPath(double x, double y)
2724 {
2725 #ifndef USE_ROSEN_DRAWING
2726     return IsPointInPathByColor(x, y, skPath_, SK_ColorRED);
2727 #else
2728     return IsPointInPathByColor(x, y, path_, RSColor::COLOR_RED);
2729 #endif
2730 }
2731 
IsPointInPath(const RefPtr<CanvasPath2D> & path,double x,double y)2732 bool RosenRenderOffscreenCanvas::IsPointInPath(const RefPtr<CanvasPath2D>& path, double x, double y)
2733 {
2734     TranspareCmdToPath(path);
2735 #ifndef USE_ROSEN_DRAWING
2736     return IsPointInPathByColor(x, y, skPath2d_, SK_ColorRED);
2737 #else
2738     return IsPointInPathByColor(x, y, path2d_, RSColor::COLOR_RED);
2739 #endif
2740 }
2741 
IsPointInStroke(double x,double y)2742 bool RosenRenderOffscreenCanvas::IsPointInStroke(double x, double y)
2743 {
2744 #ifndef USE_ROSEN_DRAWING
2745     return IsPointInPathByColor(x, y, skPath_, SK_ColorBLUE);
2746 #else
2747     return IsPointInPathByColor(x, y, path_, RSColor::COLOR_BLUE);
2748 #endif
2749 }
2750 
IsPointInStroke(const RefPtr<CanvasPath2D> & path,double x,double y)2751 bool RosenRenderOffscreenCanvas::IsPointInStroke(const RefPtr<CanvasPath2D>& path, double x, double y)
2752 {
2753     TranspareCmdToPath(path);
2754 #ifndef USE_ROSEN_DRAWING
2755     return IsPointInPathByColor(x, y, skPath2d_, SK_ColorBLUE);
2756 #else
2757     return IsPointInPathByColor(x, y, path2d_, RSColor::COLOR_BLUE);
2758 #endif
2759 }
2760 
InitFilterFunc()2761 void RosenRenderOffscreenCanvas::InitFilterFunc()
2762 {
2763     filterFunc_["grayscale"] = [&](const std::string& percentage) {
2764         SetGrayFilter(percentage);
2765     };
2766     filterFunc_["sepia"] = [&](const std::string& percentage) {
2767         SetSepiaFilter(percentage);
2768     };
2769     filterFunc_["invert"] = [&](const std::string& percentage) {
2770         SetInvertFilter(percentage);
2771     };
2772     filterFunc_["opacity"] = [&](const std::string& percentage) {
2773         SetOpacityFilter(percentage);
2774     };
2775     filterFunc_["brightness"] = [&](const std::string& percentage) {
2776         SetBrightnessFilter(percentage);
2777     };
2778     filterFunc_["contrast"] = [&](const std::string& percentage) {
2779         SetContrastFilter(percentage);
2780     };
2781     filterFunc_["blur"] = [&](const std::string& percentage) {
2782         SetBlurFilter(percentage);
2783     };
2784     filterFunc_["drop-shadow"] = [&](const std::string& percentage) {
2785         SetDropShadowFilter(percentage);
2786     };
2787     filterFunc_["saturate"] = [&](const std::string& percentage) {
2788         SetSaturateFilter(percentage);
2789     };
2790     filterFunc_["hue-rotate"] = [&](const std::string& percentage) {
2791         SetHueRotateFilter(percentage);
2792     };
2793 }
2794 
GetFilterType(std::string & filterType,std::string & filterParam)2795 bool RosenRenderOffscreenCanvas::GetFilterType(std::string& filterType, std::string& filterParam)
2796 {
2797     std::string paramData = filterParam_;
2798     size_t index = paramData.find("(");
2799     if (index == std::string::npos) {
2800         return false;
2801     }
2802     filterType = paramData.substr(0, index);
2803     filterParam = paramData.substr(index + 1);
2804     size_t endeIndex = filterParam.find(")");
2805     if (endeIndex  == std::string::npos) {
2806         return false;
2807     }
2808     filterParam.erase(endeIndex, 1);
2809     return true;
2810 }
2811 
IsPercentStr(std::string & percent)2812 bool RosenRenderOffscreenCanvas::IsPercentStr(std::string& percent)
2813 {
2814     if (percent.find("%") != std::string::npos) {
2815         size_t index = percent.find("%");
2816         percent = percent.substr(0, index);
2817         return true;
2818     }
2819     return false;
2820 }
2821 
PxStrToDouble(const std::string & str)2822 double RosenRenderOffscreenCanvas::PxStrToDouble(const std::string& str)
2823 {
2824     double ret = 0;
2825     size_t index = str.find("px");
2826     if (index != std::string::npos) {
2827         std::string result = str.substr(0, index);
2828         std::istringstream iss(result);
2829         iss >> ret;
2830     }
2831     return  ret;
2832 }
2833 
BlurStrToDouble(const std::string & str)2834 double RosenRenderOffscreenCanvas::BlurStrToDouble(const std::string& str)
2835 {
2836     double ret = 0;
2837     size_t index = str.find("px");
2838     size_t index1 = str.find("rem");
2839     size_t demIndex = std::string::npos;
2840     if (index != std::string::npos) {
2841         demIndex = index;
2842     }
2843     if (index1 != std::string::npos) {
2844         demIndex = index1;
2845     }
2846     if (demIndex != std::string::npos) {
2847         std::string result = str.substr(0, demIndex);
2848         std::istringstream iss(result);
2849         iss >> ret;
2850     }
2851     if (str.find("rem") != std::string::npos) {
2852         return  ret * 15;
2853     }
2854     return  ret;
2855 }
2856 
SetGrayFilter(const std::string & percent)2857 void RosenRenderOffscreenCanvas::SetGrayFilter(const std::string& percent)
2858 {
2859     std::string percentage = percent;
2860     bool hasPercent = IsPercentStr(percentage);
2861     float percentNum = 0.0f;
2862     std::istringstream iss(percentage);
2863     iss >> percentNum;
2864     if (hasPercent) {
2865         percentNum = percentNum / 100;
2866     }
2867     if (percentNum > 1) {
2868         percentNum = 1;
2869     }
2870     float otherColor = percentNum / 3;
2871     float primColor = 1 - 2 * otherColor;
2872     float matrix[20] = {0};
2873     matrix[0] = matrix[6] = matrix[12] = primColor;
2874     matrix[1] = matrix[2] = matrix[5] = matrix[7] = matrix[10] = matrix[11] = otherColor;
2875     matrix[18] = 1.0f;
2876     SetColorFilter(matrix);
2877 }
2878 
SetSepiaFilter(const std::string & percent)2879 void RosenRenderOffscreenCanvas::SetSepiaFilter(const std::string& percent)
2880 {
2881     std::string percentage = percent;
2882     bool hasPercent = IsPercentStr(percentage);
2883     float percentNum = 0.0f;
2884     std::istringstream iss(percentage);
2885     iss >> percentNum;
2886     if (hasPercent) {
2887         percentNum = percentNum / 100;
2888     }
2889     if (percentNum > 1) {
2890         percentNum = 1;
2891     }
2892     float matrix[20] = {0};
2893     matrix[0] = 1.0f - percentNum * 0.6412f;
2894     matrix[1] = percentNum * 0.7044f;
2895     matrix[2] = percentNum * 0.1368f;
2896     matrix[5] = percentNum * 0.2990f;
2897     matrix[6] = 1.0f - percentNum * 0.4130f;
2898     matrix[7] = percentNum * 0.1140f;
2899     matrix[10] = percentNum * 0.2392f;
2900     matrix[11] = percentNum * 0.4696f;
2901     matrix[12] = 1.0f - percentNum * 0.9088f;
2902     matrix[18] = 1.0f;
2903     SetColorFilter(matrix);
2904 }
2905 
SetInvertFilter(const std::string & filterParam)2906 void RosenRenderOffscreenCanvas::SetInvertFilter(const std::string& filterParam)
2907 {
2908     std::string percent = filterParam;
2909     bool hasPercent = IsPercentStr(percent);
2910     float percentage = 0.0f;
2911     std::istringstream iss(percent);
2912     iss >> percentage;
2913     if (hasPercent) {
2914         percentage = percentage / 100;
2915     }
2916 
2917     float matrix[20] = {0};
2918     matrix[0] = matrix[6] = matrix[12] = 1.0 - 2.0 * percentage;
2919     matrix[4] = matrix[9] = matrix[14] = percentage;
2920     matrix[18] = 1.0f;
2921     SetColorFilter(matrix);
2922 }
2923 
SetOpacityFilter(const std::string & filterParam)2924 void RosenRenderOffscreenCanvas::SetOpacityFilter(const std::string& filterParam)
2925 {
2926     std::string percent = filterParam;
2927     bool hasPercent = IsPercentStr(percent);
2928     float percentage = 0.0f;
2929     std::istringstream iss(percent);
2930     iss >> percentage;
2931     if (hasPercent) {
2932         percentage = percentage / 100;
2933     }
2934 
2935     float matrix[20] = {0};
2936     matrix[0] = matrix[6] = matrix[12] = 1.0f;
2937     matrix[18] = percentage;
2938     SetColorFilter(matrix);
2939 }
2940 
SetBrightnessFilter(const std::string & percent)2941 void RosenRenderOffscreenCanvas::SetBrightnessFilter(const std::string& percent)
2942 {
2943     std::string perStr = percent;
2944     bool hasPercent = IsPercentStr(perStr);
2945     float percentage = 0.0f;
2946     std::istringstream iss(perStr);
2947     iss >> percentage;
2948     if (hasPercent) {
2949         percentage = percentage / 100;
2950     }
2951 
2952     if (percentage < 0) {
2953         return;
2954     }
2955     float matrix[20] = {0};
2956     matrix[0] = matrix[6] = matrix[12] = percentage;
2957     matrix[18] = 1.0f;
2958     SetColorFilter(matrix);
2959 }
2960 
SetContrastFilter(const std::string & percent)2961 void RosenRenderOffscreenCanvas::SetContrastFilter(const std::string& percent)
2962 {
2963     std::string perStr = percent;
2964     float percentage = 0.0f;
2965     bool hasPercent = IsPercentStr(perStr);
2966     std::istringstream iss(perStr);
2967     iss >> percentage;
2968     if (hasPercent) {
2969         percentage = percentage / 100;
2970     }
2971 
2972     float matrix[20] = {0};
2973     matrix[0] = matrix[6] = matrix[12] = percentage;
2974     matrix[4] = matrix[9] = matrix[14] = 0.5f * (1 - percentage);
2975     matrix[18] = 1;
2976     SetColorFilter(matrix);
2977 }
2978 
SetBlurFilter(const std::string & percent)2979 void RosenRenderOffscreenCanvas::SetBlurFilter(const std::string& percent)
2980 {
2981 #ifndef USE_ROSEN_DRAWING
2982 #ifndef NEW_SKIA
2983     imagePaint_.setImageFilter(SkBlurImageFilter::Make(BlurStrToDouble(percent), BlurStrToDouble(percent), nullptr));
2984 #else
2985     imagePaint_.setImageFilter(SkImageFilters::Blur(BlurStrToDouble(percent), BlurStrToDouble(percent), nullptr));
2986 #endif
2987 #else
2988     auto filter = imageBrush_.GetFilter();
2989     filter.SetImageFilter(RSImageFilter::CreateBlurImageFilter(
2990         BlurStrToDouble(percent), BlurStrToDouble(percent), RSTileMode::DECAL, nullptr));
2991     imageBrush_.SetFilter(filter);
2992 #endif
2993 }
2994 
SetDropShadowFilter(const std::string & percent)2995 void RosenRenderOffscreenCanvas::SetDropShadowFilter(const std::string& percent)
2996 {
2997     std::vector<std::string> offsets;
2998     StringUtils::StringSplitter(percent, ' ', offsets);
2999     if (offsets.empty() || offsets.size() != 4) {
3000         return;
3001     }
3002     imageShadow_.SetOffsetX(PxStrToDouble(offsets[0]));
3003     imageShadow_.SetOffsetY(PxStrToDouble(offsets[1]));
3004     imageShadow_.SetBlurRadius(PxStrToDouble(offsets[2]));
3005     imageShadow_.SetColor(Color::FromString(offsets[3]));
3006 }
3007 
SetSaturateFilter(const std::string & filterParam)3008 void RosenRenderOffscreenCanvas::SetSaturateFilter(const std::string& filterParam)
3009 {
3010     std::string percent = filterParam;
3011     bool hasPercent = IsPercentStr(percent);
3012     float percentage = 0.0f;
3013     std::istringstream iss(percent);
3014     iss >> percentage;
3015     if (hasPercent) {
3016         percentage = percentage / 100;
3017     }
3018     double N = percentage;
3019     float matrix[20] = {0};
3020     matrix[0] = 0.3086f * (1 - N) + N;
3021     matrix[1] = matrix[11] = 0.6094f * (1 - N);
3022     matrix[2] = matrix[7] = 0.0820f * (1 - N);
3023     matrix[5] = matrix[10] = 0.3086f * (1 - N);
3024     matrix[6] = 0.6094f * (1 - N) + N;
3025     matrix[12] = 0.0820f * (1 - N) + N;
3026     matrix[18] = 1.0f;
3027     SetColorFilter(matrix);
3028 }
3029 
SetHueRotateFilter(const std::string & filterParam)3030 void RosenRenderOffscreenCanvas::SetHueRotateFilter(const std::string& filterParam)
3031 {
3032     std::string percent = filterParam;
3033     float degree = 0.0f;
3034     if (percent.find("deg") != std::string::npos) {
3035         size_t index = percent.find("deg");
3036         percent = percent.substr(0, index);
3037         std::istringstream iss(percent);
3038         iss >> degree;
3039     }
3040     if (percent.find("turn") != std::string::npos) {
3041         size_t index = percent.find("turn");
3042         percent = percent.substr(0, index);
3043         std::istringstream iss(percent);
3044         iss >> degree;
3045         degree = degree * 360;
3046     }
3047     if (percent.find("rad") != std::string::npos) {
3048         size_t index = percent.find("rad");
3049         percent = percent.substr(0, index);
3050         std::istringstream iss(percent);
3051         iss >> degree;
3052         degree = degree * 180 / 3.142f;
3053     }
3054 
3055     while (GreatOrEqual(degree, 360)) {
3056         degree -= 360;
3057     }
3058 
3059     float matrix[20] = {0};
3060     int32_t type = degree / 120;
3061     float N = (degree - 120 * type) / 120;
3062     switch (type) {
3063         case 0:
3064             // degree is in 0-120
3065             matrix[0] = matrix[6] = matrix[12] = 1 - N;
3066             matrix[2] = matrix[5] = matrix[11] = N;
3067             matrix[18] = 1.0f;
3068             break;
3069         case 1:
3070             // degree is in 120-240
3071             matrix[1] = matrix[7] = matrix[10] = N;
3072             matrix[2] = matrix[5] = matrix[11] = 1 - N;
3073             matrix[18] = 1.0f;
3074             break;
3075         case 2:
3076             // degree is in 240-360
3077             matrix[0] = matrix[6] = matrix[11] = N;
3078             matrix[1] = matrix[7] = matrix[10] = 1 - N;
3079             matrix[18] = 1.0f;
3080             break;
3081         default:
3082             break;
3083     }
3084     SetColorFilter(matrix);
3085 }
3086 
SetColorFilter(float matrix[20])3087 void RosenRenderOffscreenCanvas::SetColorFilter(float matrix[20])
3088 {
3089 #ifndef USE_ROSEN_DRAWING
3090 #ifdef USE_SYSTEM_SKIA
3091     matrix[4] *= 255;
3092     matrix[9] *= 255;
3093     matrix[14] *= 255;
3094     matrix[19] *= 255;
3095     imagePaint_.setColorFilter(SkColorFilter::MakeMatrixFilterRowMajor255(matrix));
3096 #else
3097     imagePaint_.setColorFilter(SkColorFilters::Matrix(matrix));
3098 #endif
3099 #else
3100     RSColorMatrix colorMatrix;
3101     matrix[4] *= 255;
3102     matrix[9] *= 255;
3103     matrix[14] *= 255;
3104     matrix[19] *= 255;
3105     colorMatrix.SetArray(matrix);
3106     auto filter = imageBrush_.GetFilter();
3107     filter.SetColorFilter(RSColorFilter::CreateMatrixColorFilter(colorMatrix));
3108     imageBrush_.SetFilter(filter);
3109 #endif
3110 }
3111 } // namespace OHOS::Ace
3112