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