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