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