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