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