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