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