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