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