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