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