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