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