• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components/custom_paint/rosen_render_custom_paint.h"
17 
18 #include <cmath>
19 
20 #include "flutter/lib/ui/text/font_collection.h"
21 #include "flutter/third_party/txt/src/txt/paragraph_builder.h"
22 #include "flutter/third_party/txt/src/txt/paragraph_style.h"
23 #include "flutter/third_party/txt/src/txt/paragraph_txt.h"
24 #include "render_service_client/core/ui/rs_node.h"
25 #include "third_party/bounds_checking_function/include/securec.h"
26 #include "third_party/skia/include/core/SkBlendMode.h"
27 #include "third_party/skia/include/core/SkCanvas.h"
28 #include "third_party/skia/include/core/SkColor.h"
29 #include "third_party/skia/include/core/SkImage.h"
30 #include "third_party/skia/include/core/SkMaskFilter.h"
31 #include "third_party/skia/include/core/SkPoint.h"
32 #include "third_party/skia/include/core/SkSurface.h"
33 #include "third_party/skia/include/effects/SkDashPathEffect.h"
34 #include "third_party/skia/include/effects/SkGradientShader.h"
35 #include "third_party/skia/include/encode/SkJpegEncoder.h"
36 #include "third_party/skia/include/encode/SkPngEncoder.h"
37 #include "third_party/skia/include/encode/SkWebpEncoder.h"
38 #include "third_party/skia/include/utils/SkBase64.h"
39 #include "third_party/skia/include/utils/SkParsePath.h"
40 
41 #include "base/geometry/dimension.h"
42 #include "base/i18n/localization.h"
43 #include "base/image/pixel_map.h"
44 #include "base/json/json_util.h"
45 #include "base/log/ace_trace.h"
46 #include "base/utils/linear_map.h"
47 #include "base/utils/measure_util.h"
48 #include "base/utils/string_utils.h"
49 #include "base/utils/utils.h"
50 #include "bridge/common/utils/utils.h"
51 #include "core/components/calendar/rosen_render_calendar.h"
52 #include "core/components/common/painter/rosen_decoration_painter.h"
53 #include "core/components/font/constants_converter.h"
54 #include "core/components/font/rosen_font_collection.h"
55 #include "core/components/text/text_theme.h"
56 #include "core/image/flutter_image_cache.h"
57 #include "core/image/image_cache.h"
58 #include "core/image/image_provider.h"
59 #include "core/pipeline/base/rosen_render_context.h"
60 
61 #ifdef CANVAS_USE_GPU
62 #include "core/common/graphic/environment_gl.h"
63 #endif
64 
65 namespace OHOS::Ace {
66 namespace {
67 
68 constexpr double HANGING_PERCENT = 0.8;
69 constexpr double HALF_CIRCLE_ANGLE = 180.0;
70 constexpr double FULL_CIRCLE_ANGLE = 360.0;
71 constexpr int32_t IMAGE_CACHE_COUNT = 50;
72 #ifdef CANVAS_USE_GPU
73 constexpr int32_t UNREF_OBJECT_DELAY = 100;
74 #endif
75 
76 constexpr double DEFAULT_QUALITY = 0.92;
77 constexpr int32_t MAX_LENGTH = 2048 * 2048;
78 const std::string UNSUPPORTED = "data:image/png";
79 const std::string URL_PREFIX = "data:";
80 const std::string URL_SYMBOL = ";base64,";
81 const std::string IMAGE_PNG = "image/png";
82 const std::string IMAGE_JPEG = "image/jpeg";
83 const std::string IMAGE_WEBP = "image/webp";
84 const std::u16string ELLIPSIS = u"\u2026";
85 
86 // If args is empty or invalid format, use default: image/png
GetMimeType(const std::string & args)87 std::string GetMimeType(const std::string& args)
88 {
89     // Args example: ["image/png"]
90     std::vector<std::string> values;
91     StringUtils::StringSplitter(args, '"', values);
92     if (values.size() < 3) {
93         return IMAGE_PNG;
94     } else {
95         // Convert to lowercase string.
96         for (size_t i = 0; i < values[1].size(); ++i) {
97             values[1][i] = static_cast<uint8_t>(tolower(values[1][i]));
98         }
99         return values[1];
100     }
101 }
102 
103 // Quality need between 0.0 and 1.0 for MimeType jpeg and webp
GetQuality(const std::string & args)104 double GetQuality(const std::string& args)
105 {
106     // Args example: ["image/jpeg", 0.8]
107     std::vector<std::string> values;
108     StringUtils::StringSplitter(args, ',', values);
109     if (values.size() < 2) {
110         return DEFAULT_QUALITY;
111     }
112     auto mimeType = GetMimeType(args);
113     if (mimeType != IMAGE_JPEG && mimeType != IMAGE_WEBP) {
114         return DEFAULT_QUALITY;
115     }
116     double quality = StringUtils::StringToDouble(values[1]);
117     if (quality < 0.0 || quality > 1.0) {
118         return DEFAULT_QUALITY;
119     }
120     return quality;
121 }
122 
123 template<typename T, typename N>
ConvertEnumToSkEnum(T key,const LinearEnumMapNode<T,N> * map,size_t length,N defaultValue)124 N ConvertEnumToSkEnum(T key, const LinearEnumMapNode<T, N>* map, size_t length, N defaultValue)
125 {
126     int64_t index = BinarySearchFindIndex(map, length, key);
127     return index != -1 ? map[index].value : defaultValue;
128 }
129 
130 const LinearEnumMapNode<CompositeOperation, SkBlendMode> SK_BLEND_MODE_TABLE[] = {
131     { CompositeOperation::SOURCE_OVER, SkBlendMode::kSrcOver },
132     { CompositeOperation::SOURCE_ATOP, SkBlendMode::kSrcATop },
133     { CompositeOperation::SOURCE_IN, SkBlendMode::kSrcIn },
134     { CompositeOperation::SOURCE_OUT, SkBlendMode::kSrcOut },
135     { CompositeOperation::DESTINATION_OVER, SkBlendMode::kDstOver },
136     { CompositeOperation::DESTINATION_ATOP, SkBlendMode::kDstATop },
137     { CompositeOperation::DESTINATION_IN, SkBlendMode::kDstIn },
138     { CompositeOperation::DESTINATION_OUT, SkBlendMode::kDstOut },
139     { CompositeOperation::LIGHTER, SkBlendMode::kLighten },
140     { CompositeOperation::COPY, SkBlendMode::kSrc },
141     { CompositeOperation::XOR, SkBlendMode::kXor },
142 };
143 constexpr size_t BLEND_MODE_SIZE = ArraySize(SK_BLEND_MODE_TABLE);
144 
145 } // namespace
146 
RosenRenderCustomPaint()147 RosenRenderCustomPaint::RosenRenderCustomPaint()
148 {
149     auto currentDartState = flutter::UIDartState::Current();
150     if (!currentDartState) {
151         return;
152     }
153 
154     renderTaskHolder_ = MakeRefPtr<FlutterRenderTaskHolder>(currentDartState->GetSkiaUnrefQueue(),
155         currentDartState->GetIOManager(), currentDartState->GetTaskRunners().GetIOTaskRunner());
156 
157     InitImageCallbacks();
158 }
159 
~RosenRenderCustomPaint()160 RosenRenderCustomPaint::~RosenRenderCustomPaint()
161 {
162 #ifdef CANVAS_USE_GPU
163     auto pipeline = context_.Upgrade();
164     if (!pipeline) {
165         return;
166     }
167     pipeline->PostTaskToRT([this]() { environment_ = nullptr; });
168 #endif
169 }
170 
171 #ifdef CANVAS_USE_GPU
InitializeEglContext()172 void RosenRenderCustomPaint::InitializeEglContext()
173 {
174     ACE_SCOPED_TRACE("InitializeEglContext");
175     if (environment_) {
176         return;
177     }
178     environment_ = EnvironmentGL::GetCurrent();
179     if (environment_) {
180         return;
181     }
182     auto pipeline = context_.Upgrade();
183     if (!pipeline) {
184         return;
185     }
186     pipeline->PostTaskToRT([this]() { environment_ = EnvironmentGL::MakeSharedGLContext(); });
187     if (!environment_) {
188         LOGE("Make shared GLContext failed.");
189         return;
190     }
191     environment_->MakeCurrent();
192     environment_->MakeGrContext();
193 }
194 #endif
195 
CreateSurface(double viewScale)196 bool RosenRenderCustomPaint::CreateSurface(double viewScale)
197 {
198 #ifdef CANVAS_USE_GPU
199     InitializeEglContext();
200     if (!environment_) {
201         return false;
202     }
203     auto grContext = environment_->GetGrContext();
204     if (!grContext) {
205         LOGE("grContext_ is nullptr.");
206         return false;
207     }
208     auto imageInfo = SkImageInfo::MakeN32(GetLayoutSize().Width() * viewScale, GetLayoutSize().Height() * viewScale,
209         kOpaque_SkAlphaType, SkColorSpace::MakeSRGB());
210 
211     const SkSurfaceProps surfaceProps(SkSurfaceProps::InitType::kLegacyFontHost_InitType);
212     surface_ = SkSurface::MakeRenderTarget(
213         grContext.get(), SkBudgeted::kNo, imageInfo, 0, kBottomLeft_GrSurfaceOrigin, &surfaceProps);
214     if (!surface_) {
215         LOGE("surface_ is nullptr");
216         return false;
217     }
218     skCanvas_ = std::unique_ptr<SkCanvas>(surface_->getCanvas());
219     lastLayoutSize_ = GetLayoutSize();
220     skCanvas_->drawColor(0x0);
221 
222     auto imageInfo = SkImageInfo::Make(GetLayoutSize().Width() * viewScale, GetLayoutSize().Height() * viewScale,
223         SkColorType::kRGBA_8888_SkColorType, SkAlphaType::kUnpremul_SkAlphaType);
224     cacheBitmap_.reset();
225     cacheBitmap_.allocPixels(imageInfo);
226     cacheBitmap_.eraseColor(SK_ColorTRANSPARENT);
227     cacheCanvas_ = std::make_unique<SkCanvas>(cacheBitmap_);
228     return true;
229 #else
230     return false;
231 #endif
232 }
233 
CreateBitmap(double viewScale)234 void RosenRenderCustomPaint::CreateBitmap(double viewScale)
235 {
236     auto imageInfo = SkImageInfo::Make(GetLayoutSize().Width() * viewScale, GetLayoutSize().Height() * viewScale,
237         SkColorType::kRGBA_8888_SkColorType, SkAlphaType::kUnpremul_SkAlphaType);
238     canvasCache_.reset();
239     cacheBitmap_.reset();
240     canvasCache_.allocPixels(imageInfo);
241     cacheBitmap_.allocPixels(imageInfo);
242     canvasCache_.eraseColor(SK_ColorTRANSPARENT);
243     cacheBitmap_.eraseColor(SK_ColorTRANSPARENT);
244     skCanvas_ = std::make_unique<SkCanvas>(canvasCache_);
245     cacheCanvas_ = std::make_unique<SkCanvas>(cacheBitmap_);
246 }
247 
Paint(RenderContext & context,const Offset & offset)248 void RosenRenderCustomPaint::Paint(RenderContext& context, const Offset& offset)
249 {
250     ACE_SCOPED_TRACE("RosenRenderCustomPaint::Paint");
251     auto canvas = static_cast<RosenRenderContext*>(&context)->GetCanvas();
252     if (auto rsNode = static_cast<RosenRenderContext*>(&context)->GetRSNode()) {
253         rsNode->SetClipToFrame(true);
254     }
255     if (!canvas) {
256         return;
257     }
258     auto pipeline = context_.Upgrade();
259     if (!pipeline) {
260         return;
261     }
262     // use physical pixel to store bitmap
263     double viewScale = pipeline->GetViewScale();
264     if (lastLayoutSize_ != GetLayoutSize()) {
265         if (GetLayoutSize().IsInfinite()) {
266             return;
267         }
268         if (!CreateSurface(viewScale)) {
269             CreateBitmap(viewScale);
270         }
271         lastLayoutSize_ = GetLayoutSize();
272     }
273     if (!skCanvas_) {
274         LOGE("skCanvas_ is null");
275         return;
276     }
277     skCanvas_->scale(viewScale, viewScale);
278     TriggerOnReadyEvent();
279 
280     for (const auto& task : tasks_) {
281         task(*this, offset);
282     }
283     skCanvas_->scale(1.0 / viewScale, 1.0 / viewScale);
284     tasks_.clear();
285 
286     canvas->save();
287     canvas->scale(1.0 / viewScale, 1.0 / viewScale);
288 #ifdef CANVAS_USE_GPU
289     if (surface_) {
290         ACE_SCOPED_TRACE("surface draw");
291         surface_->flush(SkSurface::BackendSurfaceAccess::kNoAccess, { .fFlags = kSyncCpu_GrFlushFlag });
292         auto image = surface_->makeImageSnapshot();
293         if (!image) {
294             return;
295         }
296         canvas->drawImage(image, 0, 0, nullptr);
297         pipeline->GetTaskExecutor()->PostDelayedTask([image] {}, TaskExecutor::TaskType::UI, UNREF_OBJECT_DELAY);
298     } else {
299         canvas->drawBitmap(canvasCache_, 0.0f, 0.0f);
300     }
301 #else
302     canvas->drawBitmap(canvasCache_, 0.0f, 0.0f);
303 #endif
304     canvas->restore();
305 }
306 
GetStrokePaint()307 SkPaint RosenRenderCustomPaint::GetStrokePaint()
308 {
309     static const LinearEnumMapNode<LineJoinStyle, SkPaint::Join> skLineJoinTable[] = {
310         { LineJoinStyle::MITER, SkPaint::Join::kMiter_Join },
311         { LineJoinStyle::ROUND, SkPaint::Join::kRound_Join },
312         { LineJoinStyle::BEVEL, SkPaint::Join::kBevel_Join },
313     };
314     static const LinearEnumMapNode<LineCapStyle, SkPaint::Cap> skLineCapTable[] = {
315         { LineCapStyle::BUTT, SkPaint::Cap::kButt_Cap },
316         { LineCapStyle::ROUND, SkPaint::Cap::kRound_Cap },
317         { LineCapStyle::SQUARE, SkPaint::Cap::kSquare_Cap },
318     };
319     SkPaint paint;
320     paint.setColor(strokeState_.GetColor().GetValue());
321     paint.setStyle(SkPaint::Style::kStroke_Style);
322     paint.setStrokeJoin(ConvertEnumToSkEnum(
323         strokeState_.GetLineJoin(), skLineJoinTable, ArraySize(skLineJoinTable), SkPaint::Join::kMiter_Join));
324     paint.setStrokeCap(ConvertEnumToSkEnum(
325         strokeState_.GetLineCap(), skLineCapTable, ArraySize(skLineCapTable), SkPaint::Cap::kButt_Cap));
326     paint.setStrokeWidth(static_cast<SkScalar>(strokeState_.GetLineWidth()));
327     paint.setStrokeMiter(static_cast<SkScalar>(strokeState_.GetMiterLimit()));
328 
329     // set line Dash
330     UpdateLineDash(paint);
331 
332     // set global alpha
333     if (globalState_.HasGlobalAlpha()) {
334         paint.setAlphaf(globalState_.GetAlpha());
335     }
336     return paint;
337 }
338 
ToDataURL(const std::string & args)339 std::string RosenRenderCustomPaint::ToDataURL(const std::string& args)
340 {
341     std::string mimeType = GetMimeType(args);
342     double quality = GetQuality(args);
343     double width = GetLayoutSize().Width();
344     double height = GetLayoutSize().Height();
345     SkBitmap tempCache;
346     tempCache.allocPixels(SkImageInfo::Make(width, height, SkColorType::kBGRA_8888_SkColorType,
347         (mimeType == IMAGE_JPEG) ? SkAlphaType::kOpaque_SkAlphaType : SkAlphaType::kUnpremul_SkAlphaType));
348     bool isGpuEnable = false;
349     bool success = false;
350 #ifdef CANVAS_USE_GPU
351     if (surface_) {
352         isGpuEnable = true;
353         auto pipeline = context_.Upgrade();
354         if (!pipeline) {
355             return UNSUPPORTED;
356         }
357         double viewScale = pipeline->GetViewScale();
358         SkBitmap bitmap;
359         auto imageInfo = SkImageInfo::Make(lastLayoutSize_.Width() * viewScale, lastLayoutSize_.Height() * viewScale,
360             SkColorType::kRGBA_8888_SkColorType, SkAlphaType::kUnpremul_SkAlphaType);
361         bitmap.allocPixels(imageInfo);
362         if (!surface_->readPixels(bitmap, 0, 0)) {
363             LOGE("surface readPixels failed when ToDataURL.");
364             return UNSUPPORTED;
365         }
366         success = bitmap.pixmap().scalePixels(tempCache.pixmap(), SkFilterQuality::kHigh_SkFilterQuality);
367         if (!success) {
368             LOGE("scalePixels failed when ToDataURL.");
369             return UNSUPPORTED;
370         }
371     }
372 #endif
373     if (!isGpuEnable) {
374         if (canvasCache_.empty()) {
375             LOGE("Bitmap is empty");
376             return UNSUPPORTED;
377         }
378 
379         success = canvasCache_.pixmap().scalePixels(tempCache.pixmap(), SkFilterQuality::kHigh_SkFilterQuality);
380         if (!success) {
381             LOGE("scalePixels failed when ToDataURL.");
382             return UNSUPPORTED;
383         }
384     }
385     SkPixmap src = tempCache.pixmap();
386     SkDynamicMemoryWStream dst;
387     if (mimeType == IMAGE_JPEG) {
388         SkJpegEncoder::Options options;
389         options.fQuality = quality * 100;
390         success = SkJpegEncoder::Encode(&dst, src, options);
391     } else if (mimeType == IMAGE_WEBP) {
392         SkWebpEncoder::Options options;
393         options.fQuality = quality * 100.0;
394         success = SkWebpEncoder::Encode(&dst, src, options);
395     } else {
396         mimeType = IMAGE_PNG;
397         SkPngEncoder::Options options;
398         success = SkPngEncoder::Encode(&dst, src, options);
399     }
400     if (!success) {
401         LOGE("Encode failed when ToDataURL.");
402         return UNSUPPORTED;
403     }
404     auto result = dst.detachAsData();
405     if (result == nullptr) {
406         LOGE("DetachAsData failed when ToDataURL.");
407         return UNSUPPORTED;
408     }
409     size_t len = SkBase64::Encode(result->data(), result->size(), nullptr);
410     if (len > MAX_LENGTH) {
411         LOGE("ToDataURL failed, image too large.");
412         return UNSUPPORTED;
413     }
414     SkString info(len);
415     SkBase64::Encode(result->data(), result->size(), info.writable_str());
416     return std::string(URL_PREFIX).append(mimeType).append(URL_SYMBOL).append(info.c_str());
417 }
418 
SetAntiAlias(bool isEnabled)419 void RosenRenderCustomPaint::SetAntiAlias(bool isEnabled)
420 {
421     antiAlias_ = isEnabled;
422 }
423 
TransferFromImageBitmap(const RefPtr<OffscreenCanvas> & offscreenCanvas)424 void RosenRenderCustomPaint::TransferFromImageBitmap(const RefPtr<OffscreenCanvas>& offscreenCanvas)
425 {
426     std::unique_ptr<ImageData> imageData =
427         offscreenCanvas->GetImageData(0, 0, offscreenCanvas->GetWidth(), offscreenCanvas->GetHeight());
428     ImageData* imageDataPtr = imageData.get();
429     if (imageData != nullptr) {
430         PutImageData(Offset(0, 0), *imageDataPtr);
431     }
432 }
433 
FillRect(const Offset & offset,const Rect & rect)434 void RosenRenderCustomPaint::FillRect(const Offset& offset, const Rect& rect)
435 {
436     SkPaint paint;
437     paint.setAntiAlias(antiAlias_);
438     paint.setColor(fillState_.GetColor().GetValue());
439     paint.setStyle(SkPaint::Style::kFill_Style);
440     SkRect skRect = SkRect::MakeLTRB(rect.Left() + offset.GetX(), rect.Top() + offset.GetY(),
441         rect.Right() + offset.GetX(), offset.GetY() + rect.Bottom());
442     if (HasShadow()) {
443         SkPath path;
444         path.addRect(skRect);
445         RosenDecorationPainter::PaintShadow(path, shadow_, skCanvas_.get());
446     }
447     if (fillState_.GetGradient().IsValid()) {
448         UpdatePaintShader(offset, paint, fillState_.GetGradient());
449     }
450     if (fillState_.GetPattern().IsValid()) {
451         UpdatePaintShader(fillState_.GetPattern(), paint);
452     }
453     if (globalState_.HasGlobalAlpha()) {
454         paint.setAlphaf(globalState_.GetAlpha()); // update the global alpha after setting the color
455     }
456     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
457         skCanvas_->drawRect(skRect, paint);
458     } else {
459         InitPaintBlend(cachePaint_);
460         cacheCanvas_->drawRect(skRect, paint);
461         skCanvas_->drawBitmap(cacheBitmap_, 0, 0, &cachePaint_);
462         cacheBitmap_.eraseColor(0);
463     }
464 }
465 
StrokeRect(const Offset & offset,const Rect & rect)466 void RosenRenderCustomPaint::StrokeRect(const Offset& offset, const Rect& rect)
467 {
468     SkPaint paint = GetStrokePaint();
469     paint.setAntiAlias(antiAlias_);
470     SkRect skRect = SkRect::MakeLTRB(rect.Left() + offset.GetX(), rect.Top() + offset.GetY(),
471         rect.Right() + offset.GetX(), offset.GetY() + rect.Bottom());
472     if (HasShadow()) {
473         SkPath path;
474         path.addRect(skRect);
475         RosenDecorationPainter::PaintShadow(path, shadow_, skCanvas_.get());
476     }
477     if (strokeState_.GetGradient().IsValid()) {
478         UpdatePaintShader(offset, paint, strokeState_.GetGradient());
479     }
480     if (strokeState_.GetPattern().IsValid()) {
481         UpdatePaintShader(strokeState_.GetPattern(), paint);
482     }
483         if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
484         skCanvas_->drawRect(skRect, paint);
485     } else {
486         InitPaintBlend(cachePaint_);
487         cacheCanvas_->drawRect(skRect, paint);
488         skCanvas_->drawBitmap(cacheBitmap_, 0, 0, &cachePaint_);
489         cacheBitmap_.eraseColor(0);
490     }
491 }
492 
ClearRect(const Offset & offset,const Rect & rect)493 void RosenRenderCustomPaint::ClearRect(const Offset& offset, const Rect& rect)
494 {
495     SkPaint paint;
496     paint.setAntiAlias(antiAlias_);
497     paint.setBlendMode(SkBlendMode::kClear);
498     auto skRect = SkRect::MakeLTRB(rect.Left() + offset.GetX(), rect.Top() + offset.GetY(),
499         rect.Right() + offset.GetX(), rect.Bottom() + offset.GetY());
500     skCanvas_->drawRect(skRect, paint);
501 }
502 
FillText(const Offset & offset,const std::string & text,double x,double y)503 void RosenRenderCustomPaint::FillText(const Offset& offset, const std::string& text, double x, double y)
504 {
505     if (!UpdateParagraph(offset, text, false, HasShadow())) {
506         return;
507     }
508     PaintText(offset, x, y, false, HasShadow());
509 }
510 
StrokeText(const Offset & offset,const std::string & text,double x,double y)511 void RosenRenderCustomPaint::StrokeText(const Offset& offset, const std::string& text, double x, double y)
512 {
513     if (HasShadow()) {
514         if (!UpdateParagraph(offset, text, true, true)) {
515             return;
516         }
517         PaintText(offset, x, y, true, true);
518     }
519 
520     if (!UpdateParagraph(offset, text, true)) {
521         return;
522     }
523     PaintText(offset, x, y, true);
524 }
525 
MeasureTextInner(const MeasureContext & context)526 double RosenRenderCustomPaint::MeasureTextInner(const MeasureContext& context)
527 {
528     using namespace Constants;
529     txt::ParagraphStyle style;
530     auto fontCollection = RosenFontCollection::GetInstance().GetFontCollection();
531     if (!fontCollection) {
532         LOGW("fontCollection is null");
533         return 0.0;
534     }
535     std::unique_ptr<txt::ParagraphBuilder> builder = txt::ParagraphBuilder::CreateTxtBuilder(style, fontCollection);
536     txt::TextStyle txtStyle;
537     std::vector<std::string> fontFamilies;
538     if (context.fontSize) {
539         txtStyle.font_size = context.fontSize.value().ConvertToPx();
540     } else {
541         auto context = PipelineBase::GetCurrentContext();
542         auto textTheme = context->GetTheme<TextTheme>();
543         txtStyle.font_size = textTheme->GetTextStyle().GetFontSize().ConvertToPx();
544     }
545     txtStyle.font_style = ConvertTxtFontStyle(context.fontStyle);
546     FontWeight fontWeightStr = StringUtils::StringToFontWeight(context.fontWeight);
547     txtStyle.font_weight = ConvertTxtFontWeight(fontWeightStr);
548     StringUtils::StringSplitter(context.fontFamily, ',', fontFamilies);
549     txtStyle.font_families = fontFamilies;
550     if (context.letterSpacing.has_value()) {
551         txtStyle.letter_spacing = context.letterSpacing.value().ConvertToPx();
552     }
553 
554     builder->PushStyle(txtStyle);
555     builder->AddText(StringUtils::Str8ToStr16(context.textContent));
556     auto paragraph = builder->Build();
557     if (!paragraph) {
558         return 0.0;
559     }
560     paragraph->Layout(Size::INFINITE_SIZE);
561     return std::ceil(paragraph->GetLongestLine());
562 }
563 
MeasureTextSizeInner(const MeasureContext & context)564 Size RosenRenderCustomPaint::MeasureTextSizeInner(const MeasureContext& context)
565 {
566     using namespace Constants;
567     auto fontCollection = RosenFontCollection::GetInstance().GetFontCollection();
568     if (!fontCollection) {
569         LOGW("fontCollection is null");
570         return Size(0.0, 0.0);
571     }
572     txt::ParagraphStyle style;
573     style.text_align = ConvertTxtTextAlign(context.textAlign);
574     if (context.textOverlayFlow == TextOverflow::ELLIPSIS) {
575         style.ellipsis = ELLIPSIS;
576     }
577     if (GreatNotEqual(context.maxlines, 0.0)) {
578         style.max_lines = context.maxlines;
579     }
580 
581     std::unique_ptr<txt::ParagraphBuilder> builder = txt::ParagraphBuilder::CreateTxtBuilder(style, fontCollection);
582     txt::TextStyle txtStyle;
583     std::vector<std::string> fontFamilies;
584     if (context.fontSize.has_value()) {
585         txtStyle.font_size = context.fontSize.value().ConvertToPx();
586     } else {
587         auto context = PipelineBase::GetCurrentContext();
588         auto textTheme = context->GetTheme<TextTheme>();
589         txtStyle.font_size = textTheme->GetTextStyle().GetFontSize().ConvertToPx();
590     }
591     txtStyle.font_style = ConvertTxtFontStyle(context.fontStyle);
592     FontWeight fontWeightStr = StringUtils::StringToFontWeight(context.fontWeight);
593     txtStyle.font_weight = ConvertTxtFontWeight(fontWeightStr);
594     StringUtils::StringSplitter(context.fontFamily, ',', fontFamilies);
595     txtStyle.font_families = fontFamilies;
596     if (context.letterSpacing.has_value()) {
597         txtStyle.letter_spacing = context.letterSpacing.value().ConvertToPx();
598     }
599     if (context.lineHeight.has_value()) {
600         if (context.lineHeight->Unit() == DimensionUnit::PERCENT) {
601             txtStyle.has_height_override = true;
602             txtStyle.height = context.lineHeight->Value();
603         } else {
604             auto lineHeight = context.lineHeight.value().ConvertToPx();
605             if (!NearEqual(lineHeight, txtStyle.font_size) && (lineHeight > 0.0) && (!NearZero(txtStyle.font_size))) {
606                 txtStyle.height = lineHeight / txtStyle.font_size;
607                 txtStyle.has_height_override = true;
608             }
609         }
610     }
611     builder->PushStyle(txtStyle);
612     std::string content = context.textContent;
613     StringUtils::TransformStrCase(content, static_cast<int32_t>(context.textCase));
614     builder->AddText(StringUtils::Str8ToStr16(content));
615     auto paragraph = builder->Build();
616     if (!paragraph) {
617         return Size(0.0, 0.0);
618     }
619     if (context.constraintWidth.has_value()) {
620         paragraph->Layout(context.constraintWidth.value().ConvertToPx());
621     } else {
622         paragraph->Layout(Size::INFINITE_SIZE);
623     }
624     double textWidth = 0.0;
625     auto* paragraphTxt = static_cast<txt::ParagraphTxt*>(paragraph.get());
626     if (paragraphTxt->GetLineCount() == 1) {
627         textWidth = std::max(paragraph->GetLongestLine(), paragraph->GetMaxIntrinsicWidth());
628     } else {
629         textWidth = paragraph->GetLongestLine();
630     }
631     auto sizeWidth = std::min(paragraph->GetMaxWidth(), textWidth);
632     sizeWidth =
633         context.constraintWidth.has_value() ? context.constraintWidth.value().ConvertToPx() : std::ceil(sizeWidth);
634 
635     float baselineOffset = 0.0;
636     if (context.baselineOffset.has_value()) {
637         baselineOffset = static_cast<float>(context.baselineOffset.value().ConvertToPx());
638     }
639     float heightFinal = static_cast<float>(paragraph->GetHeight()) + std::fabs(baselineOffset);
640 
641     return Size(sizeWidth, heightFinal);
642 }
643 
MeasureText(const std::string & text,const PaintState & state)644 double RosenRenderCustomPaint::MeasureText(const std::string& text, const PaintState& state)
645 {
646     using namespace Constants;
647     txt::ParagraphStyle style;
648     style.text_align = ConvertTxtTextAlign(state.GetTextAlign());
649     auto fontCollection = RosenFontCollection::GetInstance().GetFontCollection();
650     if (!fontCollection) {
651         LOGW("MeasureText: fontCollection is null");
652         return 0.0;
653     }
654     std::unique_ptr<txt::ParagraphBuilder> builder = txt::ParagraphBuilder::CreateTxtBuilder(style, fontCollection);
655     txt::TextStyle txtStyle;
656     ConvertTxtStyle(state.GetTextStyle(), context_, txtStyle);
657     txtStyle.font_size = state.GetTextStyle().GetFontSize().Value();
658     builder->PushStyle(txtStyle);
659     builder->AddText(StringUtils::Str8ToStr16(text));
660     auto paragraph = builder->Build();
661     paragraph->Layout(Size::INFINITE_SIZE);
662     return paragraph->GetMaxIntrinsicWidth();
663 }
664 
MeasureTextHeight(const std::string & text,const PaintState & state)665 double RosenRenderCustomPaint::MeasureTextHeight(const std::string& text, const PaintState& state)
666 {
667     using namespace Constants;
668     txt::ParagraphStyle style;
669     style.text_align = ConvertTxtTextAlign(state.GetTextAlign());
670     auto fontCollection = RosenFontCollection::GetInstance().GetFontCollection();
671     if (!fontCollection) {
672         LOGW("MeasureText: fontCollection is null");
673         return 0.0;
674     }
675     std::unique_ptr<txt::ParagraphBuilder> builder = txt::ParagraphBuilder::CreateTxtBuilder(style, fontCollection);
676     txt::TextStyle txtStyle;
677     ConvertTxtStyle(state.GetTextStyle(), context_, txtStyle);
678     txtStyle.font_size = state.GetTextStyle().GetFontSize().Value();
679     builder->PushStyle(txtStyle);
680     builder->AddText(StringUtils::Str8ToStr16(text));
681     auto paragraph = builder->Build();
682     paragraph->Layout(Size::INFINITE_SIZE);
683     return paragraph->GetHeight();
684 }
685 
MeasureTextMetrics(const std::string & text,const PaintState & state)686 TextMetrics RosenRenderCustomPaint::MeasureTextMetrics(const std::string& text, const PaintState& state)
687 {
688     using namespace Constants;
689     txt::ParagraphStyle style;
690     style.text_align = ConvertTxtTextAlign(state.GetTextAlign());
691     auto fontCollection = RosenFontCollection::GetInstance().GetFontCollection();
692     if (!fontCollection) {
693         LOGW("MeasureText: fontCollection is null");
694         return { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
695     }
696     std::unique_ptr<txt::ParagraphBuilder> builder = txt::ParagraphBuilder::CreateTxtBuilder(style, fontCollection);
697     txt::TextStyle txtStyle;
698     ConvertTxtStyle(state.GetTextStyle(), context_, txtStyle);
699     txtStyle.font_size = state.GetTextStyle().GetFontSize().Value();
700     builder->PushStyle(txtStyle);
701     builder->AddText(StringUtils::Str8ToStr16(text));
702     auto paragraph = builder->Build();
703     paragraph->Layout(Size::INFINITE_SIZE);
704 
705     auto textAlign = state.GetTextAlign();
706     auto textBaseLine = state.GetTextStyle().GetTextBaseline();
707 
708     auto width = paragraph->GetMaxIntrinsicWidth();
709     auto height = paragraph->GetHeight();
710 
711     auto actualBoundingBoxLeft = -GetAlignOffset(textAlign, paragraph);
712     auto actualBoundingBoxRight = width - actualBoundingBoxLeft;
713     auto actualBoundingBoxAscent = -GetBaselineOffset(textBaseLine, paragraph);
714     auto actualBoundingBoxDescent = height - actualBoundingBoxAscent;
715 
716     return { width, height, actualBoundingBoxLeft, actualBoundingBoxRight, actualBoundingBoxAscent,
717         actualBoundingBoxDescent };
718 }
719 
PaintText(const Offset & offset,double x,double y,bool isStroke,bool hasShadow)720 void RosenRenderCustomPaint::PaintText(const Offset& offset, double x, double y, bool isStroke, bool hasShadow)
721 {
722     paragraph_->Layout(GetLayoutSize().Width());
723     if (GetLayoutSize().Width() > paragraph_->GetMaxIntrinsicWidth()) {
724         paragraph_->Layout(std::ceil(paragraph_->GetMaxIntrinsicWidth()));
725     }
726     auto align = isStroke ? strokeState_.GetTextAlign() : fillState_.GetTextAlign();
727     double dx = offset.GetX() + x + GetAlignOffset(align, paragraph_);
728     auto baseline =
729         isStroke ? strokeState_.GetTextStyle().GetTextBaseline() : fillState_.GetTextStyle().GetTextBaseline();
730     double dy = offset.GetY() + y + GetBaselineOffset(baseline, paragraph_);
731 
732     if (hasShadow) {
733         skCanvas_->save();
734         auto shadowOffsetX = shadow_.GetOffset().GetX();
735         auto shadowOffsetY = shadow_.GetOffset().GetY();
736         paragraph_->Paint(skCanvas_.get(), dx + shadowOffsetX, dy + shadowOffsetY);
737         skCanvas_->restore();
738         return;
739     }
740 
741     paragraph_->Paint(skCanvas_.get(), dx, dy);
742 }
743 
GetAlignOffset(TextAlign align,std::unique_ptr<txt::Paragraph> & paragraph)744 double RosenRenderCustomPaint::GetAlignOffset(TextAlign align, std::unique_ptr<txt::Paragraph>& paragraph)
745 {
746     double x = 0.0;
747     switch (align) {
748         case TextAlign::LEFT:
749             x = 0.0;
750             break;
751         case TextAlign::START:
752             x = (GetTextDirection() == TextDirection::LTR) ? 0.0 : -paragraph->GetMaxIntrinsicWidth();
753             break;
754         case TextAlign::RIGHT:
755             x = -paragraph->GetMaxIntrinsicWidth();
756             break;
757         case TextAlign::END:
758             x = (GetTextDirection() == TextDirection::LTR) ? -paragraph->GetMaxIntrinsicWidth() : 0.0;
759             break;
760         case TextAlign::CENTER:
761             x = -paragraph->GetMaxIntrinsicWidth() / 2;
762             break;
763         default:
764             x = 0.0;
765             break;
766     }
767     return x;
768 }
769 
GetBaselineOffset(TextBaseline baseline,std::unique_ptr<txt::Paragraph> & paragraph)770 double RosenRenderCustomPaint::GetBaselineOffset(TextBaseline baseline, std::unique_ptr<txt::Paragraph>& paragraph)
771 {
772     double y = 0.0;
773     switch (baseline) {
774         case TextBaseline::ALPHABETIC:
775             y = -paragraph->GetAlphabeticBaseline();
776             break;
777         case TextBaseline::IDEOGRAPHIC:
778             y = -paragraph->GetIdeographicBaseline();
779             break;
780         case TextBaseline::BOTTOM:
781             y = -paragraph->GetHeight();
782             break;
783         case TextBaseline::TOP:
784             y = 0.0;
785             break;
786         case TextBaseline::MIDDLE:
787             y = -paragraph->GetHeight() / 2;
788             break;
789         case TextBaseline::HANGING:
790             y = -HANGING_PERCENT * (paragraph->GetHeight() - paragraph->GetAlphabeticBaseline());
791             break;
792         default:
793             y = -paragraph->GetAlphabeticBaseline();
794             break;
795     }
796     return y;
797 }
798 
MoveTo(const Offset & offset,double x,double y)799 void RosenRenderCustomPaint::MoveTo(const Offset& offset, double x, double y)
800 {
801     skPath_.moveTo(SkDoubleToScalar(x + offset.GetX()), SkDoubleToScalar(y + offset.GetY()));
802 }
803 
LineTo(const Offset & offset,double x,double y)804 void RosenRenderCustomPaint::LineTo(const Offset& offset, double x, double y)
805 {
806     skPath_.lineTo(SkDoubleToScalar(x + offset.GetX()), SkDoubleToScalar(y + offset.GetY()));
807 }
808 
BezierCurveTo(const Offset & offset,const BezierCurveParam & param)809 void RosenRenderCustomPaint::BezierCurveTo(const Offset& offset, const BezierCurveParam& param)
810 {
811     skPath_.cubicTo(SkDoubleToScalar(param.cp1x + offset.GetX()), SkDoubleToScalar(param.cp1y + offset.GetY()),
812         SkDoubleToScalar(param.cp2x + offset.GetX()), SkDoubleToScalar(param.cp2y + offset.GetY()),
813         SkDoubleToScalar(param.x + offset.GetX()), SkDoubleToScalar(param.y + offset.GetY()));
814 }
815 
QuadraticCurveTo(const Offset & offset,const QuadraticCurveParam & param)816 void RosenRenderCustomPaint::QuadraticCurveTo(const Offset& offset, const QuadraticCurveParam& param)
817 {
818     skPath_.quadTo(SkDoubleToScalar(param.cpx + offset.GetX()), SkDoubleToScalar(param.cpy + offset.GetY()),
819         SkDoubleToScalar(param.x + offset.GetX()), SkDoubleToScalar(param.y + offset.GetY()));
820 }
821 
Arc(const Offset & offset,const ArcParam & param)822 void RosenRenderCustomPaint::Arc(const Offset& offset, const ArcParam& param)
823 {
824     double left = param.x - param.radius + offset.GetX();
825     double top = param.y - param.radius + offset.GetY();
826     double right = param.x + param.radius + offset.GetX();
827     double bottom = param.y + param.radius + offset.GetY();
828     double startAngle = param.startAngle * HALF_CIRCLE_ANGLE / M_PI;
829     double endAngle = param.endAngle * HALF_CIRCLE_ANGLE / M_PI;
830     double sweepAngle = endAngle - startAngle;
831     if (param.anticlockwise) {
832         sweepAngle =
833             endAngle > startAngle ? (std::fmod(sweepAngle, FULL_CIRCLE_ANGLE) - FULL_CIRCLE_ANGLE) : sweepAngle;
834     } else {
835         sweepAngle =
836             endAngle > startAngle ? sweepAngle : (std::fmod(sweepAngle, FULL_CIRCLE_ANGLE) + FULL_CIRCLE_ANGLE);
837     }
838     auto rect = SkRect::MakeLTRB(left, top, right, bottom);
839     if (NearEqual(std::fmod(sweepAngle, FULL_CIRCLE_ANGLE), 0.0) && !NearEqual(startAngle, endAngle)) {
840         // draw circle
841         double half = GreatNotEqual(sweepAngle, 0.0) ? HALF_CIRCLE_ANGLE : -HALF_CIRCLE_ANGLE;
842         skPath_.arcTo(rect, SkDoubleToScalar(startAngle), SkDoubleToScalar(half), false);
843         skPath_.arcTo(rect, SkDoubleToScalar(half + startAngle), SkDoubleToScalar(half), false);
844     } else if (!NearEqual(std::fmod(sweepAngle, FULL_CIRCLE_ANGLE), 0.0) && abs(sweepAngle) > FULL_CIRCLE_ANGLE) {
845         double half = GreatNotEqual(sweepAngle, 0.0) ? HALF_CIRCLE_ANGLE : -HALF_CIRCLE_ANGLE;
846         skPath_.arcTo(rect, SkDoubleToScalar(startAngle), SkDoubleToScalar(half), false);
847         skPath_.arcTo(rect, SkDoubleToScalar(half + startAngle), SkDoubleToScalar(half), false);
848         skPath_.arcTo(rect, SkDoubleToScalar(half + half + startAngle), SkDoubleToScalar(sweepAngle), false);
849     } else {
850         skPath_.arcTo(rect, SkDoubleToScalar(startAngle), SkDoubleToScalar(sweepAngle), false);
851     }
852 }
853 
ArcTo(const Offset & offset,const ArcToParam & param)854 void RosenRenderCustomPaint::ArcTo(const Offset& offset, const ArcToParam& param)
855 {
856     double x1 = param.x1 + offset.GetX();
857     double y1 = param.y1 + offset.GetY();
858     double x2 = param.x2 + offset.GetX();
859     double y2 = param.y2 + offset.GetY();
860     double radius = param.radius;
861     skPath_.arcTo(SkDoubleToScalar(x1), SkDoubleToScalar(y1), SkDoubleToScalar(x2), SkDoubleToScalar(y2),
862         SkDoubleToScalar(radius));
863 }
864 
Ellipse(const Offset & offset,const EllipseParam & param)865 void RosenRenderCustomPaint::Ellipse(const Offset& offset, const EllipseParam& param)
866 {
867     // Init the start and end angle, then calculated the sweepAngle.
868     double startAngle = std::fmod(param.startAngle, M_PI * 2.0);
869     double endAngle = std::fmod(param.endAngle, M_PI * 2.0);
870     startAngle = (startAngle < 0.0 ? startAngle + M_PI * 2.0 : startAngle) * HALF_CIRCLE_ANGLE / M_PI;
871     endAngle = (endAngle < 0.0 ? endAngle + M_PI * 2.0 : endAngle) * HALF_CIRCLE_ANGLE / M_PI;
872     if (NearEqual(param.startAngle, param.endAngle)) {
873         return; // Just return when startAngle is same as endAngle.
874     }
875     double rotation = param.rotation * HALF_CIRCLE_ANGLE / M_PI;
876     double sweepAngle = endAngle - startAngle;
877     if (param.anticlockwise) {
878         if (sweepAngle > 0.0) { // Make sure the sweepAngle is negative when anticlockwise.
879             sweepAngle -= FULL_CIRCLE_ANGLE;
880         }
881     } else {
882         if (sweepAngle < 0.0) { // Make sure the sweepAngle is positive when clockwise.
883             sweepAngle += FULL_CIRCLE_ANGLE;
884         }
885     }
886 
887     // Init the oval Rect(left, top, right, bottom).
888     double left = param.x - param.radiusX + offset.GetX();
889     double top = param.y - param.radiusY + offset.GetY();
890     double right = param.x + param.radiusX + offset.GetX();
891     double bottom = param.y + param.radiusY + offset.GetY();
892     auto rect = SkRect::MakeLTRB(left, top, right, bottom);
893     if (!NearZero(rotation)) {
894         SkMatrix matrix;
895         matrix.setRotate(-rotation, param.x + offset.GetX(), param.y + offset.GetY());
896         skPath_.transform(matrix);
897     }
898     if (NearZero(sweepAngle) && !NearZero(param.endAngle - param.startAngle)) {
899         // The entire ellipse needs to be drawn with two arcTo.
900         skPath_.arcTo(rect, startAngle, HALF_CIRCLE_ANGLE, false);
901         skPath_.arcTo(rect, startAngle + HALF_CIRCLE_ANGLE, HALF_CIRCLE_ANGLE, false);
902     } else {
903         skPath_.arcTo(rect, startAngle, sweepAngle, false);
904     }
905     if (!NearZero(rotation)) {
906         SkMatrix matrix;
907         matrix.setRotate(rotation, param.x + offset.GetX(), param.y + offset.GetY());
908         skPath_.transform(matrix);
909     }
910 }
911 
AddRect(const Offset & offset,const Rect & rect)912 void RosenRenderCustomPaint::AddRect(const Offset& offset, const Rect& rect)
913 {
914     SkRect skRect = SkRect::MakeLTRB(rect.Left() + offset.GetX(), rect.Top() + offset.GetY(),
915         rect.Right() + offset.GetX(), offset.GetY() + rect.Bottom());
916     skPath_.addRect(skRect);
917 }
918 
SetFillRuleForPath(const CanvasFillRule & rule)919 void RosenRenderCustomPaint::SetFillRuleForPath(const CanvasFillRule& rule)
920 {
921     if (rule == CanvasFillRule::NONZERO) {
922         skPath_.setFillType(SkPath::FillType::kWinding_FillType);
923     } else if (rule == CanvasFillRule::EVENODD) {
924         skPath_.setFillType(SkPath::FillType::kEvenOdd_FillType);
925     }
926 }
927 
SetFillRuleForPath2D(const CanvasFillRule & rule)928 void RosenRenderCustomPaint::SetFillRuleForPath2D(const CanvasFillRule& rule)
929 {
930     if (rule == CanvasFillRule::NONZERO) {
931         skPath2d_.setFillType(SkPath::FillType::kWinding_FillType);
932     } else if (rule == CanvasFillRule::EVENODD) {
933         skPath2d_.setFillType(SkPath::FillType::kEvenOdd_FillType);
934     }
935 }
936 
ParsePath2D(const Offset & offset,const RefPtr<CanvasPath2D> & path)937 void RosenRenderCustomPaint::ParsePath2D(const Offset& offset, const RefPtr<CanvasPath2D>& path)
938 {
939     for (const auto& [cmd, args] : path->GetCaches()) {
940         switch (cmd) {
941             case PathCmd::CMDS: {
942                 Path2DAddPath(offset, args);
943                 break;
944             }
945             case PathCmd::TRANSFORM: {
946                 Path2DSetTransform(offset, args);
947                 break;
948             }
949             case PathCmd::MOVE_TO: {
950                 Path2DMoveTo(offset, args);
951                 break;
952             }
953             case PathCmd::LINE_TO: {
954                 Path2DLineTo(offset, args);
955                 break;
956             }
957             case PathCmd::ARC: {
958                 Path2DArc(offset, args);
959                 break;
960             }
961             case PathCmd::ARC_TO: {
962                 Path2DArcTo(offset, args);
963                 break;
964             }
965             case PathCmd::QUADRATIC_CURVE_TO: {
966                 Path2DQuadraticCurveTo(offset, args);
967                 break;
968             }
969             case PathCmd::BEZIER_CURVE_TO: {
970                 Path2DBezierCurveTo(offset, args);
971                 break;
972             }
973             case PathCmd::ELLIPSE: {
974                 Path2DEllipse(offset, args);
975                 break;
976             }
977             case PathCmd::RECT: {
978                 Path2DRect(offset, args);
979                 break;
980             }
981             case PathCmd::CLOSE_PATH: {
982                 Path2DClosePath(offset, args);
983                 break;
984             }
985             default: {
986                 break;
987             }
988         }
989     }
990 }
991 
Fill(const Offset & offset)992 void RosenRenderCustomPaint::Fill(const Offset& offset)
993 {
994     SkPaint paint;
995     paint.setAntiAlias(antiAlias_);
996     paint.setColor(fillState_.GetColor().GetValue());
997     paint.setStyle(SkPaint::Style::kFill_Style);
998     if (HasShadow()) {
999         RosenDecorationPainter::PaintShadow(skPath_, shadow_, skCanvas_.get());
1000     }
1001     if (fillState_.GetGradient().IsValid()) {
1002         UpdatePaintShader(offset, paint, fillState_.GetGradient());
1003     }
1004     if (fillState_.GetPattern().IsValid()) {
1005         UpdatePaintShader(fillState_.GetPattern(), paint);
1006     }
1007     if (globalState_.HasGlobalAlpha()) {
1008         paint.setAlphaf(globalState_.GetAlpha());
1009     }
1010     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
1011         skCanvas_->drawPath(skPath_, paint);
1012     } else {
1013         InitPaintBlend(cachePaint_);
1014         cacheCanvas_->drawPath(skPath_, paint);
1015         skCanvas_->drawBitmap(cacheBitmap_, 0, 0, &cachePaint_);
1016         cacheBitmap_.eraseColor(0);
1017     }
1018 }
1019 
Fill(const Offset & offset,const RefPtr<CanvasPath2D> & path)1020 void RosenRenderCustomPaint::Fill(const Offset& offset, const RefPtr<CanvasPath2D>& path)
1021 {
1022     if (path == nullptr) {
1023         LOGE("Fill failed, target path is null.");
1024         return;
1025     }
1026     ParsePath2D(offset, path);
1027     Path2DFill(offset);
1028     skPath2d_.reset();
1029 }
1030 
Stroke(const Offset & offset)1031 void RosenRenderCustomPaint::Stroke(const Offset& offset)
1032 {
1033     SkPaint paint = GetStrokePaint();
1034     paint.setAntiAlias(antiAlias_);
1035     if (HasShadow()) {
1036         RosenDecorationPainter::PaintShadow(skPath_, shadow_, skCanvas_.get());
1037     }
1038     if (strokeState_.GetGradient().IsValid()) {
1039         UpdatePaintShader(offset, paint, strokeState_.GetGradient());
1040     }
1041     if (strokeState_.GetPattern().IsValid()) {
1042         UpdatePaintShader(strokeState_.GetPattern(), paint);
1043     }
1044     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
1045         skCanvas_->drawPath(skPath_, paint);
1046     } else {
1047         InitPaintBlend(cachePaint_);
1048         cacheCanvas_->drawPath(skPath_, paint);
1049         skCanvas_->drawBitmap(cacheBitmap_, 0, 0, &cachePaint_);
1050         cacheBitmap_.eraseColor(0);
1051     }
1052 }
1053 
Stroke(const Offset & offset,const RefPtr<CanvasPath2D> & path)1054 void RosenRenderCustomPaint::Stroke(const Offset& offset, const RefPtr<CanvasPath2D>& path)
1055 {
1056     if (path == nullptr) {
1057         LOGE("Stroke failed, target path is null.");
1058         return;
1059     }
1060     ParsePath2D(offset, path);
1061     Path2DStroke(offset);
1062     skPath2d_.reset();
1063 }
1064 
Path2DAddPath(const Offset & offset,const PathArgs & args)1065 void RosenRenderCustomPaint::Path2DAddPath(const Offset& offset, const PathArgs& args)
1066 {
1067     SkPath out;
1068     SkParsePath::FromSVGString(args.cmds.c_str(), &out);
1069     skPath2d_.addPath(out);
1070 }
1071 
Path2DSetTransform(const Offset & offset,const PathArgs & args)1072 void RosenRenderCustomPaint::Path2DSetTransform(const Offset& offset, const PathArgs& args)
1073 {
1074     SkMatrix skMatrix;
1075     double scaleX = args.para1;
1076     double skewX = args.para2;
1077     double skewY = args.para3;
1078     double scaleY = args.para4;
1079     double translateX = args.para5;
1080     double translateY = args.para6;
1081     skMatrix.setAll(scaleX, skewY, translateX, skewX, scaleY, translateY, 0, 0, 1);
1082     skPath2d_.transform(skMatrix);
1083 }
1084 
Path2DMoveTo(const Offset & offset,const PathArgs & args)1085 void RosenRenderCustomPaint::Path2DMoveTo(const Offset& offset, const PathArgs& args)
1086 {
1087     double x = args.para1 + offset.GetX();
1088     double y = args.para2 + offset.GetY();
1089     skPath2d_.moveTo(x, y);
1090 }
1091 
Path2DLineTo(const Offset & offset,const PathArgs & args)1092 void RosenRenderCustomPaint::Path2DLineTo(const Offset& offset, const PathArgs& args)
1093 {
1094     double x = args.para1 + offset.GetX();
1095     double y = args.para2 + offset.GetY();
1096     skPath2d_.lineTo(x, y);
1097 }
1098 
Path2DArc(const Offset & offset,const PathArgs & args)1099 void RosenRenderCustomPaint::Path2DArc(const Offset& offset, const PathArgs& args)
1100 {
1101     double x = args.para1;
1102     double y = args.para2;
1103     double r = args.para3;
1104     auto rect =
1105         SkRect::MakeLTRB(x - r + offset.GetX(), y - r + offset.GetY(), x + r + offset.GetX(), y + r + offset.GetY());
1106     double startAngle = args.para4 * HALF_CIRCLE_ANGLE / M_PI;
1107     double endAngle = args.para5 * HALF_CIRCLE_ANGLE / M_PI;
1108     double sweepAngle = endAngle - startAngle;
1109     if (!NearZero(args.para6)) {
1110         sweepAngle =
1111             endAngle > startAngle ? (std::fmod(sweepAngle, FULL_CIRCLE_ANGLE) - FULL_CIRCLE_ANGLE) : sweepAngle;
1112     } else {
1113         sweepAngle =
1114             endAngle > startAngle ? sweepAngle : (std::fmod(sweepAngle, FULL_CIRCLE_ANGLE) + FULL_CIRCLE_ANGLE);
1115     }
1116     if (NearEqual(std::fmod(sweepAngle, FULL_CIRCLE_ANGLE), 0.0) && !NearEqual(startAngle, endAngle)) {
1117         skPath2d_.arcTo(rect, startAngle, HALF_CIRCLE_ANGLE, false);
1118         skPath2d_.arcTo(rect, startAngle + HALF_CIRCLE_ANGLE, HALF_CIRCLE_ANGLE, false);
1119     } else if (!NearEqual(std::fmod(sweepAngle, FULL_CIRCLE_ANGLE), 0.0) && abs(sweepAngle) > FULL_CIRCLE_ANGLE) {
1120         skPath2d_.arcTo(rect, startAngle, HALF_CIRCLE_ANGLE, false);
1121         skPath2d_.arcTo(rect, startAngle + HALF_CIRCLE_ANGLE, HALF_CIRCLE_ANGLE, false);
1122         skPath2d_.arcTo(rect, startAngle + HALF_CIRCLE_ANGLE + HALF_CIRCLE_ANGLE, sweepAngle, false);
1123     } else {
1124         skPath2d_.arcTo(rect, startAngle, sweepAngle, false);
1125     }
1126 }
1127 
Path2DArcTo(const Offset & offset,const PathArgs & args)1128 void RosenRenderCustomPaint::Path2DArcTo(const Offset& offset, const PathArgs& args)
1129 {
1130     double x1 = args.para1 + offset.GetX();
1131     double y1 = args.para2 + offset.GetY();
1132     double x2 = args.para3 + offset.GetX();
1133     double y2 = args.para4 + offset.GetY();
1134     double r = args.para5;
1135     skPath2d_.arcTo(x1, y1, x2, y2, r);
1136 }
1137 
Path2DQuadraticCurveTo(const Offset & offset,const PathArgs & args)1138 void RosenRenderCustomPaint::Path2DQuadraticCurveTo(const Offset& offset, const PathArgs& args)
1139 {
1140     double cpx = args.para1 + offset.GetX();
1141     double cpy = args.para2 + offset.GetY();
1142     double x = args.para3 + offset.GetX();
1143     double y = args.para4 + offset.GetY();
1144     skPath2d_.quadTo(cpx, cpy, x, y);
1145 }
1146 
Path2DBezierCurveTo(const Offset & offset,const PathArgs & args)1147 void RosenRenderCustomPaint::Path2DBezierCurveTo(const Offset& offset, const PathArgs& args)
1148 {
1149     double cp1x = args.para1 + offset.GetX();
1150     double cp1y = args.para2 + offset.GetY();
1151     double cp2x = args.para3 + offset.GetX();
1152     double cp2y = args.para4 + offset.GetY();
1153     double x = args.para5 + offset.GetX();
1154     double y = args.para6 + offset.GetY();
1155     skPath2d_.cubicTo(cp1x, cp1y, cp2x, cp2y, x, y);
1156 }
1157 
Path2DEllipse(const Offset & offset,const PathArgs & args)1158 void RosenRenderCustomPaint::Path2DEllipse(const Offset& offset, const PathArgs& args)
1159 {
1160     if (NearEqual(args.para6, args.para7)) {
1161         return; // Just return when startAngle is same as endAngle.
1162     }
1163 
1164     double x = args.para1;
1165     double y = args.para2;
1166     double rx = args.para3;
1167     double ry = args.para4;
1168     double rotation = args.para5 * HALF_CIRCLE_ANGLE / M_PI;
1169     double startAngle = std::fmod(args.para6, M_PI * 2.0);
1170     double endAngle = std::fmod(args.para7, M_PI * 2.0);
1171     bool anticlockwise = NearZero(args.para8) ? false : true;
1172     startAngle = (startAngle < 0.0 ? startAngle + M_PI * 2.0 : startAngle) * HALF_CIRCLE_ANGLE / M_PI;
1173     endAngle = (endAngle < 0.0 ? endAngle + M_PI * 2.0 : endAngle) * HALF_CIRCLE_ANGLE / M_PI;
1174     double sweepAngle = endAngle - startAngle;
1175     if (anticlockwise) {
1176         if (sweepAngle > 0.0) { // Make sure the sweepAngle is negative when anticlockwise.
1177             sweepAngle -= FULL_CIRCLE_ANGLE;
1178         }
1179     } else {
1180         if (sweepAngle < 0.0) { // Make sure the sweepAngle is positive when clockwise.
1181             sweepAngle += FULL_CIRCLE_ANGLE;
1182         }
1183     }
1184     auto rect = SkRect::MakeLTRB(
1185         x - rx + offset.GetX(), y - ry + offset.GetY(), x + rx + offset.GetX(), y + ry + offset.GetY());
1186 
1187     if (!NearZero(rotation)) {
1188         SkMatrix matrix;
1189         matrix.setRotate(-rotation, x + offset.GetX(), y + offset.GetY());
1190         skPath2d_.transform(matrix);
1191     }
1192     if (NearZero(sweepAngle) && !NearZero(args.para6 - args.para7)) {
1193         // The entire ellipse needs to be drawn with two arcTo.
1194         skPath2d_.arcTo(rect, startAngle, HALF_CIRCLE_ANGLE, false);
1195         skPath2d_.arcTo(rect, startAngle + HALF_CIRCLE_ANGLE, HALF_CIRCLE_ANGLE, false);
1196     } else {
1197         skPath2d_.arcTo(rect, startAngle, sweepAngle, false);
1198     }
1199     if (!NearZero(rotation)) {
1200         SkMatrix matrix;
1201         matrix.setRotate(rotation, x + offset.GetX(), y + offset.GetY());
1202         skPath2d_.transform(matrix);
1203     }
1204 }
1205 
Path2DRect(const Offset & offset,const PathArgs & args)1206 void RosenRenderCustomPaint::Path2DRect(const Offset& offset, const PathArgs& args)
1207 {
1208     double left = args.para1 + offset.GetX();
1209     double top = args.para2 + offset.GetY();
1210     double right = args.para3 + args.para1 + offset.GetX();
1211     double bottom = args.para4 + args.para2 + offset.GetY();
1212     skPath2d_.addRect(SkRect::MakeLTRB(left, top, right, bottom));
1213 }
1214 
Path2DClosePath(const Offset & offset,const PathArgs & args)1215 void RosenRenderCustomPaint::Path2DClosePath(const Offset& offset, const PathArgs& args)
1216 {
1217     skPath2d_.close();
1218 }
1219 
Path2DStroke(const Offset & offset)1220 void RosenRenderCustomPaint::Path2DStroke(const Offset& offset)
1221 {
1222     SkPaint paint = GetStrokePaint();
1223     paint.setAntiAlias(antiAlias_);
1224     if (HasShadow()) {
1225         RosenDecorationPainter::PaintShadow(skPath2d_, shadow_, skCanvas_.get());
1226     }
1227     if (strokeState_.GetGradient().IsValid()) {
1228         UpdatePaintShader(offset, paint, strokeState_.GetGradient());
1229     }
1230     if (strokeState_.GetPattern().IsValid()) {
1231         UpdatePaintShader(strokeState_.GetPattern(), paint);
1232     }
1233     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
1234         skCanvas_->drawPath(skPath2d_, paint);
1235     } else {
1236         InitPaintBlend(cachePaint_);
1237         cacheCanvas_->drawPath(skPath2d_, paint);
1238         skCanvas_->drawBitmap(cacheBitmap_, 0, 0, &cachePaint_);
1239         cacheBitmap_.eraseColor(0);
1240     }
1241 }
1242 
Path2DFill(const Offset & offset)1243 void RosenRenderCustomPaint::Path2DFill(const Offset& offset)
1244 {
1245     SkPaint paint;
1246     paint.setAntiAlias(antiAlias_);
1247     paint.setColor(fillState_.GetColor().GetValue());
1248     paint.setStyle(SkPaint::Style::kFill_Style);
1249     if (HasShadow()) {
1250         RosenDecorationPainter::PaintShadow(skPath2d_, shadow_, skCanvas_.get());
1251     }
1252     if (fillState_.GetGradient().IsValid()) {
1253         UpdatePaintShader(offset, paint, fillState_.GetGradient());
1254     }
1255     if (fillState_.GetPattern().IsValid()) {
1256         UpdatePaintShader(fillState_.GetPattern(), paint);
1257     }
1258     if (globalState_.HasGlobalAlpha()) {
1259         paint.setAlphaf(globalState_.GetAlpha());
1260     }
1261     if (globalState_.GetType() == CompositeOperation::SOURCE_OVER) {
1262         skCanvas_->drawPath(skPath2d_, paint);
1263     } else {
1264         InitPaintBlend(cachePaint_);
1265         cacheCanvas_->drawPath(skPath2d_, paint);
1266         skCanvas_->drawBitmap(cacheBitmap_, 0, 0, &cachePaint_);
1267         cacheBitmap_.eraseColor(0);
1268     }
1269 }
1270 
Path2DClip()1271 void RosenRenderCustomPaint::Path2DClip()
1272 {
1273     skCanvas_->clipPath(skPath2d_);
1274 }
1275 
Clip()1276 void RosenRenderCustomPaint::Clip()
1277 {
1278     skCanvas_->clipPath(skPath_);
1279 }
1280 
Clip(const RefPtr<CanvasPath2D> & path)1281 void RosenRenderCustomPaint::Clip(const RefPtr<CanvasPath2D>& path)
1282 {
1283     if (path == nullptr) {
1284         LOGE("Fill failed, target path is null.");
1285         return;
1286     }
1287     auto offset = Offset(0, 0);
1288     ParsePath2D(offset, path);
1289     Path2DClip();
1290     skPath2d_.reset();
1291 }
1292 
BeginPath()1293 void RosenRenderCustomPaint::BeginPath()
1294 {
1295     skPath_.reset();
1296 }
1297 
ResetTransform()1298 void RosenRenderCustomPaint::ResetTransform()
1299 {
1300     skCanvas_->resetMatrix();
1301 }
1302 
ClosePath()1303 void RosenRenderCustomPaint::ClosePath()
1304 {
1305     skPath_.close();
1306 }
1307 
Save()1308 void RosenRenderCustomPaint::Save()
1309 {
1310     SaveStates();
1311     skCanvas_->save();
1312 }
1313 
Restore()1314 void RosenRenderCustomPaint::Restore()
1315 {
1316     RestoreStates();
1317     skCanvas_->restore();
1318 }
1319 
InitImagePaint()1320 void RosenRenderCustomPaint::InitImagePaint()
1321 {
1322     if (smoothingEnabled_) {
1323         if (smoothingQuality_ == "low") {
1324             imagePaint_.setFilterQuality(SkFilterQuality::kLow_SkFilterQuality);
1325         } else if (smoothingQuality_ == "medium") {
1326             imagePaint_.setFilterQuality(SkFilterQuality::kMedium_SkFilterQuality);
1327         } else if (smoothingQuality_ == "high") {
1328             imagePaint_.setFilterQuality(SkFilterQuality::kHigh_SkFilterQuality);
1329         } else {
1330             LOGE("Unsupported Quality type:%{public}s", smoothingQuality_.c_str());
1331         }
1332     } else {
1333         imagePaint_.setFilterQuality(SkFilterQuality::kNone_SkFilterQuality);
1334     }
1335 }
1336 
InitPaintBlend(SkPaint & paint)1337 void RosenRenderCustomPaint::InitPaintBlend(SkPaint& paint)
1338 {
1339     paint.setBlendMode(
1340         ConvertEnumToSkEnum(globalState_.GetType(), SK_BLEND_MODE_TABLE, BLEND_MODE_SIZE, SkBlendMode::kSrcOver));
1341 }
1342 
UpdateParagraph(const Offset & offset,const std::string & text,bool isStroke,bool hasShadow)1343 bool RosenRenderCustomPaint::UpdateParagraph(
1344     const Offset& offset, const std::string& text, bool isStroke, bool hasShadow)
1345 {
1346     using namespace Constants;
1347     txt::ParagraphStyle style;
1348     if (isStroke) {
1349         style.text_align = ConvertTxtTextAlign(strokeState_.GetTextAlign());
1350     } else {
1351         style.text_align = ConvertTxtTextAlign(fillState_.GetTextAlign());
1352     }
1353     auto fontCollection = RosenFontCollection::GetInstance().GetFontCollection();
1354     if (!fontCollection) {
1355         LOGW("UpdateParagraph: fontCollection is null");
1356         return false;
1357     }
1358     std::unique_ptr<txt::ParagraphBuilder> builder = txt::ParagraphBuilder::CreateTxtBuilder(style, fontCollection);
1359     txt::TextStyle txtStyle;
1360     if (!isStroke && hasShadow) {
1361         txt::TextShadow txtShadow;
1362         txtShadow.color = shadow_.GetColor().GetValue();
1363         txtShadow.offset.fX = shadow_.GetOffset().GetX();
1364         txtShadow.offset.fY = shadow_.GetOffset().GetY();
1365         txtShadow.blur_radius = shadow_.GetBlurRadius();
1366         txtStyle.text_shadows.emplace_back(txtShadow);
1367     }
1368     txtStyle.locale = Localization::GetInstance()->GetFontLocale();
1369     UpdateTextStyleForeground(offset, isStroke, txtStyle, hasShadow);
1370     builder->PushStyle(txtStyle);
1371     builder->AddText(StringUtils::Str8ToStr16(text));
1372     paragraph_ = builder->Build();
1373     return true;
1374 }
1375 
UpdateTextStyleForeground(const Offset & offset,bool isStroke,txt::TextStyle & txtStyle,bool hasShadow)1376 void RosenRenderCustomPaint::UpdateTextStyleForeground(
1377     const Offset& offset, bool isStroke, txt::TextStyle& txtStyle, bool hasShadow)
1378 {
1379     using namespace Constants;
1380     if (!isStroke) {
1381         txtStyle.color = ConvertSkColor(fillState_.GetColor());
1382         txtStyle.font_size = fillState_.GetTextStyle().GetFontSize().Value();
1383         ConvertTxtStyle(fillState_.GetTextStyle(), context_, txtStyle);
1384         if (fillState_.GetGradient().IsValid()) {
1385             SkPaint paint;
1386             paint.setStyle(SkPaint::Style::kFill_Style);
1387             UpdatePaintShader(offset, paint, fillState_.GetGradient());
1388             txtStyle.foreground = paint;
1389             txtStyle.has_foreground = true;
1390         }
1391         if (globalState_.HasGlobalAlpha()) {
1392             if (txtStyle.has_foreground) {
1393                 txtStyle.foreground.setColor(fillState_.GetColor().GetValue());
1394                 txtStyle.foreground.setAlphaf(globalState_.GetAlpha()); // set alpha after color
1395             } else {
1396                 SkPaint paint;
1397                 paint.setColor(fillState_.GetColor().GetValue());
1398                 paint.setAlphaf(globalState_.GetAlpha()); // set alpha after color
1399                 InitPaintBlend(paint);
1400                 txtStyle.foreground = paint;
1401                 txtStyle.has_foreground = true;
1402             }
1403         }
1404     } else {
1405         // use foreground to draw stroke
1406         SkPaint paint = GetStrokePaint();
1407         InitPaintBlend(paint);
1408         ConvertTxtStyle(strokeState_.GetTextStyle(), context_, txtStyle);
1409         txtStyle.font_size = strokeState_.GetTextStyle().GetFontSize().Value();
1410         if (strokeState_.GetGradient().IsValid()) {
1411             UpdatePaintShader(offset, paint, strokeState_.GetGradient());
1412         }
1413         if (hasShadow) {
1414             paint.setColor(shadow_.GetColor().GetValue());
1415             paint.setMaskFilter(SkMaskFilter::MakeBlur(SkBlurStyle::kNormal_SkBlurStyle,
1416                 RosenDecorationPainter::ConvertRadiusToSigma(shadow_.GetBlurRadius())));
1417         }
1418         txtStyle.foreground = paint;
1419         txtStyle.has_foreground = true;
1420     }
1421 }
1422 
HasShadow() const1423 bool RosenRenderCustomPaint::HasShadow() const
1424 {
1425     return !(NearZero(shadow_.GetOffset().GetX()) && NearZero(shadow_.GetOffset().GetY()) &&
1426              NearZero(shadow_.GetBlurRadius()));
1427 }
1428 
UpdatePaintShader(const Offset & offset,SkPaint & paint,const Gradient & gradient)1429 void RosenRenderCustomPaint::UpdatePaintShader(const Offset& offset, SkPaint& paint, const Gradient& gradient)
1430 {
1431     SkPoint beginPoint = SkPoint::Make(SkDoubleToScalar(gradient.GetBeginOffset().GetX() + offset.GetX()),
1432         SkDoubleToScalar(gradient.GetBeginOffset().GetY() + offset.GetY()));
1433     SkPoint endPoint = SkPoint::Make(SkDoubleToScalar(gradient.GetEndOffset().GetX() + offset.GetX()),
1434         SkDoubleToScalar(gradient.GetEndOffset().GetY() + offset.GetY()));
1435     SkPoint pts[2] = { beginPoint, endPoint };
1436     std::vector<GradientColor> gradientColors = gradient.GetColors();
1437     std::stable_sort(gradientColors.begin(), gradientColors.end(),
1438         [](auto& colorA, auto& colorB) { return colorA.GetDimension() < colorB.GetDimension(); });
1439     uint32_t colorsSize = gradientColors.size();
1440     SkColor colors[gradientColors.size()];
1441     float pos[gradientColors.size()];
1442     for (uint32_t i = 0; i < colorsSize; ++i) {
1443         const auto& gradientColor = gradientColors[i];
1444         colors[i] = gradientColor.GetColor().GetValue();
1445         pos[i] = gradientColor.GetDimension().Value();
1446     }
1447 
1448 #ifdef USE_SYSTEM_SKIA
1449     auto mode = SkShader::kClamp_TileMode;
1450 #else
1451     auto mode = SkTileMode::kClamp;
1452 #endif
1453 
1454     sk_sp<SkShader> skShader = nullptr;
1455     if (gradient.GetType() == GradientType::LINEAR) {
1456         skShader = SkGradientShader::MakeLinear(pts, colors, pos, gradientColors.size(), mode);
1457     } else {
1458         if (gradient.GetInnerRadius() <= 0.0 && beginPoint == endPoint) {
1459             skShader = SkGradientShader::MakeRadial(
1460                 endPoint, gradient.GetOuterRadius(), colors, pos, gradientColors.size(), mode);
1461         } else {
1462             skShader = SkGradientShader::MakeTwoPointConical(beginPoint, gradient.GetInnerRadius(), endPoint,
1463                 gradient.GetOuterRadius(), colors, pos, gradientColors.size(), mode);
1464         }
1465     }
1466     paint.setShader(skShader);
1467 }
1468 
Rotate(double angle)1469 void RosenRenderCustomPaint::Rotate(double angle)
1470 {
1471     skCanvas_->rotate(angle * 180 / M_PI);
1472 }
1473 
Scale(double x,double y)1474 void RosenRenderCustomPaint::Scale(double x, double y)
1475 {
1476     skCanvas_->scale(x, y);
1477 }
1478 
SetTransform(const TransformParam & param)1479 void RosenRenderCustomPaint::SetTransform(const TransformParam& param)
1480 {
1481     auto pipeline = context_.Upgrade();
1482     if (!pipeline) {
1483         return;
1484     }
1485     // use physical pixel to store bitmap
1486     double viewScale = pipeline->GetViewScale();
1487     SkMatrix skMatrix;
1488     skMatrix.setAll(param.scaleX * viewScale, param.skewY * viewScale, param.translateX * viewScale,
1489         param.skewX * viewScale, param.scaleY * viewScale, param.translateY * viewScale, 0, 0, 1);
1490     skCanvas_->setMatrix(skMatrix);
1491 }
1492 
Transform(const TransformParam & param)1493 void RosenRenderCustomPaint::Transform(const TransformParam& param)
1494 {
1495     SkMatrix skMatrix;
1496     skMatrix.setAll(param.scaleX, param.skewY, param.translateX, param.skewX, param.scaleY, param.translateY, 0, 0, 1);
1497     skCanvas_->concat(skMatrix);
1498 }
1499 
Translate(double x,double y)1500 void RosenRenderCustomPaint::Translate(double x, double y)
1501 {
1502     skCanvas_->translate(x, y);
1503 }
1504 
UpdateLineDash(SkPaint & paint)1505 void RosenRenderCustomPaint::UpdateLineDash(SkPaint& paint)
1506 {
1507     if (!strokeState_.GetLineDash().lineDash.empty()) {
1508         auto lineDashState = strokeState_.GetLineDash().lineDash;
1509         SkScalar intervals[lineDashState.size()];
1510         for (size_t i = 0; i < lineDashState.size(); ++i) {
1511             intervals[i] = SkDoubleToScalar(lineDashState[i]);
1512         }
1513         SkScalar phase = SkDoubleToScalar(strokeState_.GetLineDash().dashOffset);
1514         paint.setPathEffect(SkDashPathEffect::Make(intervals, lineDashState.size(), phase));
1515     }
1516 }
1517 
InitImageCallbacks()1518 void RosenRenderCustomPaint::InitImageCallbacks()
1519 {
1520     imageObjSuccessCallback_ = [weak = AceType::WeakClaim(this)](
1521                                    ImageSourceInfo info, const RefPtr<ImageObject>& imageObj) {
1522         auto render = weak.Upgrade();
1523         if (render->loadingSource_ == info) {
1524             render->ImageObjReady(imageObj);
1525             return;
1526         } else {
1527             LOGE("image sourceInfo_ check error, : %{public}s vs %{public}s",
1528                 render->loadingSource_.ToString().c_str(), info.ToString().c_str());
1529         }
1530     };
1531 
1532     failedCallback_ = [weak = AceType::WeakClaim(this)](ImageSourceInfo info, const std::string& errorMsg = "") {
1533         auto render = weak.Upgrade();
1534         LOGE("tkh failedCallback_");
1535         render->ImageObjFailed();
1536     };
1537 
1538     uploadSuccessCallback_ = [weak = AceType::WeakClaim(this)](
1539                                  ImageSourceInfo sourceInfo, const fml::RefPtr<flutter::CanvasImage>& image) {};
1540 
1541     onPostBackgroundTask_ = [weak = AceType::WeakClaim(this)](CancelableTask task) {};
1542 }
1543 
ImageObjReady(const RefPtr<ImageObject> & imageObj)1544 void RosenRenderCustomPaint::ImageObjReady(const RefPtr<ImageObject>& imageObj)
1545 {
1546     imageObj_ = imageObj;
1547     if (imageObj_->IsSvg()) {
1548         skiaDom_ = AceType::DynamicCast<SvgSkiaImageObject>(imageObj_)->GetSkiaDom();
1549         currentSource_ = loadingSource_;
1550         CanvasImage canvasImage = canvasImage_;
1551         TaskFunc func = [canvasImage](RenderCustomPaint& iface, const Offset& offset) {
1552             iface.DrawImage(offset, canvasImage, 0, 0);
1553         };
1554         tasks_.emplace_back(func);
1555         MarkNeedRender();
1556     } else {
1557         LOGE("image is not svg");
1558     }
1559 }
1560 
ImageObjFailed()1561 void RosenRenderCustomPaint::ImageObjFailed()
1562 {
1563     imageObj_ = nullptr;
1564     skiaDom_ = nullptr;
1565 }
1566 
DrawSvgImage(const Offset & offset,const CanvasImage & canvasImage)1567 void RosenRenderCustomPaint::DrawSvgImage(const Offset& offset, const CanvasImage& canvasImage)
1568 {
1569     const auto skCanvas = skCanvas_.get();
1570     // Make the ImageSourceInfo
1571     canvasImage_ = canvasImage;
1572     loadingSource_ = ImageSourceInfo(canvasImage.src);
1573     // get the ImageObject
1574     if (currentSource_ != loadingSource_) {
1575         ImageProvider::FetchImageObject(loadingSource_, imageObjSuccessCallback_, uploadSuccessCallback_,
1576             failedCallback_, GetContext(), true, true, true, renderTaskHolder_, onPostBackgroundTask_);
1577     }
1578 
1579     // draw the svg
1580     if (skiaDom_) {
1581         SkRect srcRect;
1582         SkRect dstRect;
1583         Offset startPoint;
1584         double scaleX = 1.0f;
1585         double scaleY = 1.0f;
1586         switch (canvasImage.flag) {
1587             case 0:
1588                 srcRect = SkRect::MakeXYWH(0, 0, skiaDom_->containerSize().width(), skiaDom_->containerSize().height());
1589                 dstRect = SkRect::MakeXYWH(canvasImage.dx, canvasImage.dy,
1590                     skiaDom_->containerSize().width(), skiaDom_->containerSize().height());
1591                 break;
1592             case 1: {
1593                 srcRect = SkRect::MakeXYWH(0, 0, skiaDom_->containerSize().width(), skiaDom_->containerSize().height());
1594                 dstRect = SkRect::MakeXYWH(canvasImage.dx, canvasImage.dy, canvasImage.dWidth, canvasImage.dHeight);
1595                 break;
1596             }
1597             case 2: {
1598                 srcRect = SkRect::MakeXYWH(canvasImage.sx, canvasImage.sy, canvasImage.sWidth, canvasImage.sHeight);
1599                 dstRect = SkRect::MakeXYWH(canvasImage.dx, canvasImage.dy, canvasImage.dWidth, canvasImage.dHeight);
1600                 break;
1601             }
1602             default:
1603                 break;
1604         }
1605         scaleX = dstRect.width() / srcRect.width();
1606         scaleY = dstRect.height() / srcRect.height();
1607         startPoint = offset  + Offset(dstRect.left(), dstRect.top())
1608 	    - Offset(srcRect.left() * scaleX, srcRect.top() * scaleY);
1609 
1610         skCanvas->save();
1611         skCanvas->clipRect(dstRect);
1612         skCanvas->translate(startPoint.GetX(), startPoint.GetY());
1613         skCanvas->scale(scaleX, scaleY);
1614         skiaDom_->render(skCanvas);
1615         skCanvas->restore();
1616     }
1617 }
1618 
DrawImage(const Offset & offset,const CanvasImage & canvasImage,double width,double height)1619 void RosenRenderCustomPaint::DrawImage(
1620     const Offset& offset, const CanvasImage& canvasImage, double width, double height)
1621 {
1622     if (!flutter::UIDartState::Current()) {
1623         return;
1624     }
1625 
1626     std::string::size_type tmp = canvasImage.src.find(".svg");
1627     if (tmp != std::string::npos) {
1628         DrawSvgImage(offset, canvasImage);
1629         return;
1630     }
1631 
1632     auto image = GetImage(canvasImage.src);
1633 
1634     if (!image) {
1635         LOGE("image is null");
1636         return;
1637     }
1638     InitImagePaint();
1639     InitPaintBlend(imagePaint_);
1640 
1641     switch (canvasImage.flag) {
1642         case 0:
1643             skCanvas_->drawImage(image, canvasImage.dx, canvasImage.dy);
1644             break;
1645         case 1: {
1646             SkRect rect = SkRect::MakeXYWH(canvasImage.dx, canvasImage.dy, canvasImage.dWidth, canvasImage.dHeight);
1647             skCanvas_->drawImageRect(image, rect, &imagePaint_);
1648             break;
1649         }
1650         case 2: {
1651             SkRect dstRect = SkRect::MakeXYWH(canvasImage.dx, canvasImage.dy, canvasImage.dWidth, canvasImage.dHeight);
1652             SkRect srcRect = SkRect::MakeXYWH(canvasImage.sx, canvasImage.sy, canvasImage.sWidth, canvasImage.sHeight);
1653             skCanvas_->drawImageRect(image, srcRect, dstRect, &imagePaint_);
1654             break;
1655         }
1656         default:
1657             break;
1658     }
1659 }
1660 
DrawPixelMap(RefPtr<PixelMap> pixelMap,const CanvasImage & canvasImage)1661 void RosenRenderCustomPaint::DrawPixelMap(RefPtr<PixelMap> pixelMap, const CanvasImage& canvasImage)
1662 {
1663     if (!flutter::UIDartState::Current()) {
1664         return;
1665     }
1666 
1667     auto context = GetContext().Upgrade();
1668     if (!context) {
1669         return;
1670     }
1671 
1672     // get skImage form pixelMap
1673     auto imageInfo = ImageProvider::MakeSkImageInfoFromPixelMap(pixelMap);
1674     SkPixmap imagePixmap(imageInfo, reinterpret_cast<const void*>(pixelMap->GetPixels()), pixelMap->GetRowBytes());
1675 
1676     // Step2: Create SkImage and draw it, using gpu or cpu
1677     sk_sp<SkImage> image;
1678     if (!renderTaskHolder_->ioManager) {
1679         image = SkImage::MakeFromRaster(imagePixmap, &PixelMap::ReleaseProc, PixelMap::GetReleaseContext(pixelMap));
1680     } else {
1681 #ifndef GPU_DISABLED
1682         image = SkImage::MakeCrossContextFromPixmap(renderTaskHolder_->ioManager->GetResourceContext().get(),
1683             imagePixmap, true, imagePixmap.colorSpace(), true);
1684 #else
1685         image = SkImage::MakeFromRaster(imagePixmap, &PixelMap::ReleaseProc, PixelMap::GetReleaseContext(pixelMap));
1686 #endif
1687     }
1688     if (!image) {
1689         LOGE("image is null");
1690         return;
1691     }
1692     InitImagePaint();
1693     InitPaintBlend(imagePaint_);
1694     switch (canvasImage.flag) {
1695         case 0:
1696             skCanvas_->drawImage(image, canvasImage.dx, canvasImage.dy);
1697             break;
1698         case 1: {
1699             SkRect rect = SkRect::MakeXYWH(canvasImage.dx, canvasImage.dy, canvasImage.dWidth, canvasImage.dHeight);
1700             skCanvas_->drawImageRect(image, rect, &imagePaint_);
1701             break;
1702         }
1703         case 2: {
1704             SkRect dstRect = SkRect::MakeXYWH(canvasImage.dx, canvasImage.dy, canvasImage.dWidth, canvasImage.dHeight);
1705             SkRect srcRect = SkRect::MakeXYWH(canvasImage.sx, canvasImage.sy, canvasImage.sWidth, canvasImage.sHeight);
1706             skCanvas_->drawImageRect(image, srcRect, dstRect, &imagePaint_);
1707             break;
1708         }
1709         default:
1710             break;
1711     }
1712 }
1713 
UpdatePaintShader(const Pattern & pattern,SkPaint & paint)1714 void RosenRenderCustomPaint::UpdatePaintShader(const Pattern& pattern, SkPaint& paint)
1715 {
1716     if (!flutter::UIDartState::Current()) {
1717         return;
1718     }
1719 
1720     auto context = GetContext().Upgrade();
1721     if (!context) {
1722         return;
1723     }
1724 
1725     auto width = pattern.GetImageWidth();
1726     auto height = pattern.GetImageHeight();
1727     auto image = GreatOrEqual(width, 0) && GreatOrEqual(height, 0)
1728                      ? ImageProvider::GetSkImage(pattern.GetImgSrc(), context, Size(width, height))
1729                      : ImageProvider::GetSkImage(pattern.GetImgSrc(), context);
1730     if (!image) {
1731         LOGE("image is null");
1732         return;
1733     }
1734     static const LinearMapNode<void (*)(sk_sp<SkImage>, SkPaint&)> staticPattern[] = {
1735         { "no-repeat",
1736             [](sk_sp<SkImage> image, SkPaint& paint) {
1737 #ifdef USE_SYSTEM_SKIA
1738                 paint.setShader(image->makeShader(SkShader::kDecal_TileMode, SkShader::kDecal_TileMode, nullptr));
1739 #else
1740                 paint.setShader(image->makeShader(SkTileMode::kDecal, SkTileMode::kDecal, nullptr));
1741 #endif
1742             } },
1743         { "repeat",
1744             [](sk_sp<SkImage> image, SkPaint& paint) {
1745 #ifdef USE_SYSTEM_SKIA
1746                 paint.setShader(image->makeShader(SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, nullptr));
1747 #else
1748                 paint.setShader(image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, nullptr));
1749 #endif
1750             } },
1751         { "repeat-x",
1752             [](sk_sp<SkImage> image, SkPaint& paint) {
1753 #ifdef USE_SYSTEM_SKIA
1754                 paint.setShader(image->makeShader(SkShader::kRepeat_TileMode, SkShader::kDecal_TileMode, nullptr));
1755 #else
1756                 paint.setShader(image->makeShader(SkTileMode::kRepeat, SkTileMode::kDecal, nullptr));
1757 #endif
1758             } },
1759         { "repeat-y",
1760             [](sk_sp<SkImage> image, SkPaint& paint) {
1761 #ifdef USE_SYSTEM_SKIA
1762                 paint.setShader(image->makeShader(SkShader::kDecal_TileMode, SkShader::kRepeat_TileMode, nullptr));
1763 #else
1764                 paint.setShader(image->makeShader(SkTileMode::kDecal, SkTileMode::kRepeat, nullptr));
1765 #endif
1766             } },
1767     };
1768     auto operatorIter = BinarySearchFindIndex(staticPattern, ArraySize(staticPattern), pattern.GetRepetition().c_str());
1769     if (operatorIter != -1) {
1770         staticPattern[operatorIter].value(image, paint);
1771     }
1772 }
1773 
PutImageData(const Offset & offset,const ImageData & imageData)1774 void RosenRenderCustomPaint::PutImageData(const Offset& offset, const ImageData& imageData)
1775 {
1776     if (imageData.data.empty()) {
1777         LOGE("PutImageData failed, image data is empty.");
1778         return;
1779     }
1780     uint32_t* data = new (std::nothrow) uint32_t[imageData.data.size()];
1781     if (data == nullptr) {
1782         LOGE("PutImageData failed, new data is null.");
1783         return;
1784     }
1785 
1786     for (uint32_t i = 0; i < imageData.data.size(); ++i) {
1787         data[i] = imageData.data[i].GetValue();
1788     }
1789     SkBitmap skBitmap;
1790     auto imageInfo = SkImageInfo::Make(imageData.dirtyWidth, imageData.dirtyHeight, SkColorType::kBGRA_8888_SkColorType,
1791         SkAlphaType::kOpaque_SkAlphaType);
1792     skBitmap.allocPixels(imageInfo);
1793     skBitmap.setPixels(data);
1794     skCanvas_->drawBitmap(skBitmap, imageData.x, imageData.y);
1795     delete[] data;
1796 }
1797 
GetImageData(double left,double top,double width,double height)1798 std::unique_ptr<ImageData> RosenRenderCustomPaint::GetImageData(double left, double top, double width, double height)
1799 {
1800     double viewScale = 1.0;
1801     auto pipeline = context_.Upgrade();
1802     if (pipeline) {
1803         viewScale = pipeline->GetViewScale();
1804     }
1805     // copy the bitmap to tempCanvas
1806     auto imageInfo =
1807         SkImageInfo::Make(width, height, SkColorType::kBGRA_8888_SkColorType, SkAlphaType::kOpaque_SkAlphaType);
1808     SkBitmap tempCache;
1809     double scaledLeft = left * viewScale;
1810     double scaledTop = top * viewScale;
1811     double dirtyWidth = width >= 0 ? width : 0;
1812     double dirtyHeight = height >= 0 ? height : 0;
1813     tempCache.allocPixels(imageInfo);
1814     int32_t size = dirtyWidth * dirtyHeight;
1815     bool isGpuEnable = false;
1816     const uint8_t* pixels = nullptr;
1817     SkCanvas tempCanvas(tempCache);
1818     auto srcRect = SkRect::MakeXYWH(scaledLeft, scaledTop, width * viewScale, height * viewScale);
1819     auto dstRect = SkRect::MakeXYWH(0.0, 0.0, dirtyWidth, dirtyHeight);
1820 #ifdef CANVAS_USE_GPU
1821     if (surface_) {
1822         isGpuEnable = true;
1823         SkBitmap bitmap;
1824         auto imageInfo = SkImageInfo::Make(lastLayoutSize_.Width() * viewScale, lastLayoutSize_.Height() * viewScale,
1825             SkColorType::kRGBA_8888_SkColorType, SkAlphaType::kUnpremul_SkAlphaType);
1826         bitmap.allocPixels(imageInfo);
1827         if (!surface_->readPixels(bitmap, 0, 0)) {
1828             LOGE("surface readPixels failed when GetImageData.");
1829         }
1830         tempCanvas.drawBitmapRect(bitmap, srcRect, dstRect, nullptr);
1831     }
1832 #endif
1833     if (!isGpuEnable) {
1834         tempCanvas.drawBitmapRect(canvasCache_, srcRect, dstRect, nullptr);
1835     }
1836     pixels = tempCache.pixmap().addr8();
1837     if (pixels == nullptr) {
1838         return nullptr;
1839     }
1840     std::unique_ptr<ImageData> imageData = std::make_unique<ImageData>();
1841     imageData->dirtyWidth = dirtyWidth;
1842     imageData->dirtyHeight = dirtyHeight;
1843     // a pixel include 4 data(blue, green, red, alpha)
1844     for (int i = 0; i < size * 4; i += 4) {
1845         auto blue = pixels[i];
1846         auto green = pixels[i + 1];
1847         auto red = pixels[i + 2];
1848         auto alpha = pixels[i + 3];
1849         imageData->data.emplace_back(Color::FromARGB(alpha, red, green, blue));
1850     }
1851     return imageData;
1852 }
1853 
GetJsonData(const std::string & path)1854 std::string RosenRenderCustomPaint::GetJsonData(const std::string& path)
1855 {
1856     AssetImageLoader imageLoader;
1857     return imageLoader.LoadJsonData(path, context_.Upgrade());
1858 }
1859 
WebGLInit(CanvasRenderContextBase * context)1860 void RosenRenderCustomPaint::WebGLInit(CanvasRenderContextBase* context)
1861 {
1862     webGLContext_ = context;
1863     if (webGLContext_) {
1864         auto pipeline = context_.Upgrade();
1865         if (!pipeline) {
1866             return;
1867         }
1868         double viewScale = pipeline->GetViewScale();
1869         if (!webglBitmap_.readyToDraw()) {
1870             auto imageInfo =
1871                 SkImageInfo::Make(GetLayoutSize().Width() * viewScale, GetLayoutSize().Height() * viewScale,
1872                     SkColorType::kRGBA_8888_SkColorType, SkAlphaType::kOpaque_SkAlphaType);
1873             webglBitmap_.allocPixels(imageInfo);
1874 #ifdef USE_SYSTEM_SKIA
1875             webglBitmap_.eraseColor(SK_ColorTRANSPARENT);
1876 #endif
1877         }
1878         webGLContext_->SetBitMapPtr(reinterpret_cast<char*>(webglBitmap_.getPixels()),
1879             webglBitmap_.width(), webglBitmap_.height());
1880     }
1881 }
1882 
WebGLUpdate()1883 void RosenRenderCustomPaint::WebGLUpdate()
1884 {
1885     LOGD("RosenRenderCustomPaint::WebGLUpdate");
1886     if (skCanvas_ && webglBitmap_.readyToDraw()) {
1887         skCanvas_->save();
1888         /* Do mirror flip */
1889         skCanvas_->setMatrix(SkMatrix::MakeScale(1.0, -1.0));
1890         skCanvas_->drawBitmap(webglBitmap_, 0, -webglBitmap_.height());
1891         skCanvas_->restore();
1892     }
1893 }
1894 
DrawBitmapMesh(const RefPtr<OffscreenCanvas> & offscreenCanvas,const std::vector<double> & mesh,int32_t column,int32_t row)1895 void RosenRenderCustomPaint::DrawBitmapMesh(const RefPtr<OffscreenCanvas>& offscreenCanvas,
1896     const std::vector<double>& mesh, int32_t column, int32_t row)
1897 {
1898     std::unique_ptr<ImageData> imageData = offscreenCanvas->GetImageData(0, 0,
1899         offscreenCanvas->GetWidth(), offscreenCanvas->GetHeight());
1900     if (imageData != nullptr) {
1901         if (imageData->data.empty()) {
1902             LOGE("PutImageData failed, image data is empty.");
1903             return;
1904         }
1905         uint32_t* data = new (std::nothrow) uint32_t[imageData->data.size()];
1906         if (data == nullptr) {
1907             LOGE("PutImageData failed, new data is null.");
1908             return;
1909         }
1910 
1911         for (uint32_t i = 0; i < imageData->data.size(); ++i) {
1912             data[i] = imageData->data[i].GetValue();
1913         }
1914         SkBitmap skBitmap;
1915         auto imageInfo = SkImageInfo::Make(imageData->dirtyWidth, imageData->dirtyHeight,
1916             SkColorType::kBGRA_8888_SkColorType, SkAlphaType::kOpaque_SkAlphaType);
1917         skBitmap.allocPixels(imageInfo);
1918         skBitmap.setPixels(data);
1919         uint32_t size = mesh.size();
1920         float verts[size];
1921         for (uint32_t i = 0; i < size; i++) {
1922             verts[i] = mesh[i];
1923         }
1924         Mesh(skBitmap, column, row, verts, 0, nullptr);
1925         delete[] data;
1926     }
1927     LOGD("RosenRenderCustomPaint::DrawBitmapMesh");
1928 }
1929 
Mesh(SkBitmap & bitmap,int column,int row,const float * vertices,const int * colors,const SkPaint * paint)1930 void RosenRenderCustomPaint::Mesh(SkBitmap& bitmap, int column, int row,
1931     const float* vertices, const int* colors, const SkPaint* paint)
1932 {
1933     const int vertCounts = (column + 1) * (row + 1);
1934     int32_t size = 6;
1935     const int indexCount = column * row * size;
1936     uint32_t flags = SkVertices::kHasTexCoords_BuilderFlag;
1937     if (colors) {
1938         flags |= SkVertices::kHasColors_BuilderFlag;
1939     }
1940     SkVertices::Builder builder(SkVertices::kTriangles_VertexMode, vertCounts, indexCount, flags);
1941     if (memcpy_s(builder.positions(), vertCounts * sizeof(SkPoint), vertices, vertCounts * sizeof(SkPoint)) != EOK) {
1942         return;
1943     }
1944     if (colors) {
1945         if (memcpy_s(builder.colors(), vertCounts * sizeof(SkColor), colors, vertCounts * sizeof(SkColor)) != EOK) {
1946             return;
1947         }
1948     }
1949     SkPoint* texsPoint = builder.texCoords();
1950     uint16_t* indices = builder.indices();
1951     const SkScalar height = SkIntToScalar(bitmap.height());
1952     const SkScalar width = SkIntToScalar(bitmap.width());
1953     if (row == 0) {
1954         LOGE("row is zero");
1955         return;
1956     }
1957     if (column == 0) {
1958         LOGE("column is zero");
1959         return;
1960     }
1961     const SkScalar dy = height / row;
1962     const SkScalar dx = width / column;
1963 
1964     SkPoint* texsPit = texsPoint;
1965     SkScalar y = 0;
1966     for (int i = 0; i <= row; i++) {
1967         if (i == row) {
1968             y = height; // to ensure numerically we hit h exactly
1969         }
1970         SkScalar x = 0;
1971         for (int j = 0; j < column; j++) {
1972             texsPit->set(x, y);
1973             texsPit += 1;
1974             x += dx;
1975         }
1976         texsPit->set(width, y);
1977         texsPit += 1;
1978         y += dy;
1979     }
1980 
1981     uint16_t* dexs = indices;
1982     int index = 0;
1983     for (int i = 0; i < row; i++) {
1984         for (int j = 0; j < column; j++) {
1985             *dexs++ = index;
1986             *dexs++ = index + column + 1;
1987             *dexs++ = index + column + 2;
1988 
1989             *dexs++ = index;
1990             *dexs++ = index + column + 2;
1991             *dexs++ = index + 1;
1992 
1993             index += 1;
1994         }
1995         index += 1;
1996     }
1997 
1998     SkPaint tempPaint;
1999     if (paint) {
2000         tempPaint = *paint;
2001     }
2002     sk_sp<SkColorFilter> colorFter;
2003     sk_sp<SkShader> shader;
2004     sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
2005 #ifdef USE_SYSTEM_SKIA
2006     shader = image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
2007 #else
2008     shader = image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp);
2009 #endif
2010     if (colorFter) {
2011         shader = shader->makeWithColorFilter(colorFter);
2012     }
2013     tempPaint.setShader(shader);
2014     skCanvas_->drawVertices(builder.detach(), SkBlendMode::kModulate, tempPaint);
2015 }
2016 
GetImage(const std::string & src)2017 sk_sp<SkImage> RosenRenderCustomPaint::GetImage(const std::string& src)
2018 {
2019     if (!imageCache_) {
2020         imageCache_ = ImageCache::Create();
2021         imageCache_->SetCapacity(IMAGE_CACHE_COUNT);
2022     }
2023     auto cacheImage = imageCache_->GetCacheImage(src);
2024     if (cacheImage && cacheImage->imagePtr) {
2025         return cacheImage->imagePtr->image();
2026     }
2027 
2028     auto context = GetContext().Upgrade();
2029     if (!context) {
2030         return nullptr;
2031     }
2032 
2033     auto image = ImageProvider::GetSkImage(src, context);
2034     if (image) {
2035         auto rasterizedImage = image->makeRasterImage();
2036         auto canvasImage = flutter::CanvasImage::Create();
2037         canvasImage->set_image({ rasterizedImage, renderTaskHolder_->unrefQueue });
2038         imageCache_->CacheImage(src, std::make_shared<CachedImage>(canvasImage));
2039         return rasterizedImage;
2040     }
2041 
2042     return image;
2043 }
2044 } // namespace OHOS::Ace
2045