1 /*
2 * Copyright (c) 2023-2024 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 "bridge/declarative_frontend/jsview/models/canvas/canvas_rendering_context_2d_model_impl.h"
17
18 #include "core/components/custom_paint/custom_paint_component.h"
19
20 #ifdef PIXEL_MAP_SUPPORTED
21 #include "pixel_map.h"
22 #endif
23
24 namespace OHOS::Ace::Framework {
SetPattern(RefPtr<AceType> pattern)25 void CanvasRenderingContext2DModelImpl::SetPattern(RefPtr<AceType> pattern)
26 {
27 pattern_ = AceType::DynamicCast<CanvasTaskPool>(pattern);
28 }
29
SetFillText(const PaintState & state,const FillTextInfo & fillTextInfo)30 void CanvasRenderingContext2DModelImpl::SetFillText(const PaintState& state, const FillTextInfo& fillTextInfo)
31 {
32 CHECK_NULL_VOID(pattern_);
33 pattern_->FillText(fillTextInfo.text, Offset(fillTextInfo.x, fillTextInfo.y));
34 }
35
SetStrokeText(const PaintState & state,const FillTextInfo & fillTextInfo)36 void CanvasRenderingContext2DModelImpl::SetStrokeText(const PaintState& state, const FillTextInfo& fillTextInfo)
37 {
38 CHECK_NULL_VOID(pattern_);
39 pattern_->StrokeText(fillTextInfo.text, Offset(fillTextInfo.x, fillTextInfo.y));
40 }
41
SetAntiAlias(bool anti)42 void CanvasRenderingContext2DModelImpl::SetAntiAlias(bool anti)
43 {
44 CHECK_NULL_VOID(pattern_);
45 pattern_->SetAntiAlias(anti);
46 }
47
SetFontWeight(const FontWeight & weight)48 void CanvasRenderingContext2DModelImpl::SetFontWeight(const FontWeight& weight)
49 {
50 CHECK_NULL_VOID(pattern_);
51 pattern_->UpdateFontWeight(weight);
52 }
53
SetFontStyle(const FontStyle & fontStyle)54 void CanvasRenderingContext2DModelImpl::SetFontStyle(const FontStyle& fontStyle)
55 {
56 CHECK_NULL_VOID(pattern_);
57 pattern_->UpdateFontStyle(fontStyle);
58 }
59
SetFontFamilies(const std::vector<std::string> & families)60 void CanvasRenderingContext2DModelImpl::SetFontFamilies(const std::vector<std::string>& families)
61 {
62 CHECK_NULL_VOID(pattern_);
63 pattern_->UpdateFontFamilies(families);
64 }
65
SetFontSize(const Dimension & size)66 void CanvasRenderingContext2DModelImpl::SetFontSize(const Dimension& size)
67 {
68 CHECK_NULL_VOID(pattern_);
69 pattern_->UpdateFontSize(size);
70 }
71
GetLineDash()72 std::vector<double> CanvasRenderingContext2DModelImpl::GetLineDash()
73 {
74 return pattern_ ? pattern_->GetLineDash().lineDash : std::vector<double> {};
75 }
76
SetFillGradient(const std::shared_ptr<Ace::Gradient> & gradient)77 void CanvasRenderingContext2DModelImpl::SetFillGradient(const std::shared_ptr<Ace::Gradient>& gradient)
78 {
79 CHECK_NULL_VOID(pattern_);
80 pattern_->UpdateFillGradient(*gradient);
81 }
82
SetFillPattern(const std::shared_ptr<Ace::Pattern> & pattern)83 void CanvasRenderingContext2DModelImpl::SetFillPattern(const std::shared_ptr<Ace::Pattern>& pattern)
84 {
85 CHECK_NULL_VOID(pattern_);
86 pattern_->UpdateFillPattern(*(pattern.get()));
87 }
88
SetFillColor(const Color & color,bool colorFlag)89 void CanvasRenderingContext2DModelImpl::SetFillColor(const Color& color, bool colorFlag)
90 {
91 if (pattern_ && colorFlag) {
92 pattern_->UpdateFillColor(color);
93 }
94 }
95
SetStrokeGradient(const std::shared_ptr<Ace::Gradient> & gradient)96 void CanvasRenderingContext2DModelImpl::SetStrokeGradient(const std::shared_ptr<Ace::Gradient>& gradient)
97 {
98 CHECK_NULL_VOID(pattern_);
99 pattern_->UpdateStrokeGradient(*gradient);
100 }
101
SetStrokePattern(const std::shared_ptr<Ace::Pattern> & pattern)102 void CanvasRenderingContext2DModelImpl::SetStrokePattern(const std::shared_ptr<Ace::Pattern>& pattern)
103 {
104 CHECK_NULL_VOID(pattern_);
105 pattern_->UpdateStrokePattern(*(pattern.get()));
106 }
107
SetStrokeColor(const Color & color,bool colorFlag)108 void CanvasRenderingContext2DModelImpl::SetStrokeColor(const Color& color, bool colorFlag)
109 {
110 if (pattern_ && colorFlag) {
111 pattern_->UpdateStrokeColor(color);
112 }
113 }
114
DrawImage(const ImageInfo & imageInfo)115 void CanvasRenderingContext2DModelImpl::DrawImage(const ImageInfo& imageInfo)
116 {
117 CHECK_NULL_VOID(pattern_);
118 if (imageInfo.isImage) {
119 pattern_->DrawImage(imageInfo.image, imageInfo.imgWidth, imageInfo.imgHeight);
120 return;
121 }
122 pattern_->DrawPixelMap(imageInfo.pixelMap, imageInfo.image);
123 }
124
PutImageData(const ImageData & imageData)125 void CanvasRenderingContext2DModelImpl::PutImageData(const ImageData& imageData)
126 {
127 CHECK_NULL_VOID(pattern_);
128 pattern_->PutImageData(imageData);
129 }
130
GetImageData(const ImageSize & imageSize)131 std::unique_ptr<ImageData> CanvasRenderingContext2DModelImpl::GetImageData(const ImageSize& imageSize)
132 {
133 return pattern_ ? pattern_->GetImageData(imageSize.left, imageSize.top, imageSize.width, imageSize.height)
134 : nullptr;
135 }
136
DrawPixelMap(const ImageInfo & imageInfo)137 void CanvasRenderingContext2DModelImpl::DrawPixelMap(const ImageInfo& imageInfo)
138 {
139 CHECK_NULL_VOID(pattern_);
140 pattern_->DrawPixelMap(imageInfo.pixelMap, imageInfo.image);
141 }
142
GetJsonData(const std::string & path)143 std::string CanvasRenderingContext2DModelImpl::GetJsonData(const std::string& path)
144 {
145 return pattern_ ? pattern_->GetJsonData(path) : "";
146 }
147
ToDataURL(const std::string & dataUrl,double quality)148 std::string CanvasRenderingContext2DModelImpl::ToDataURL(const std::string& dataUrl, double quality)
149 {
150 return pattern_ ? pattern_->ToDataURL(dataUrl + "," + std::to_string(quality)) : "";
151 }
152
SetLineCap(const LineCapStyle & lineCap)153 void CanvasRenderingContext2DModelImpl::SetLineCap(const LineCapStyle& lineCap)
154 {
155 CHECK_NULL_VOID(pattern_);
156 pattern_->UpdateLineCap(lineCap);
157 }
158
SetLineJoin(const LineJoinStyle & lineJoin)159 void CanvasRenderingContext2DModelImpl::SetLineJoin(const LineJoinStyle& lineJoin)
160 {
161 CHECK_NULL_VOID(pattern_);
162 pattern_->UpdateLineJoin(lineJoin);
163 }
164
SetMiterLimit(double limit)165 void CanvasRenderingContext2DModelImpl::SetMiterLimit(double limit)
166 {
167 CHECK_NULL_VOID(pattern_);
168 pattern_->UpdateMiterLimit(limit);
169 }
170
SetLineWidth(double lineWidth)171 void CanvasRenderingContext2DModelImpl::SetLineWidth(double lineWidth)
172 {
173 CHECK_NULL_VOID(pattern_);
174 pattern_->UpdateLineWidth(lineWidth);
175 }
176
SetGlobalAlpha(double alpha)177 void CanvasRenderingContext2DModelImpl::SetGlobalAlpha(double alpha)
178 {
179 CHECK_NULL_VOID(pattern_);
180 pattern_->UpdateGlobalAlpha(alpha);
181 }
182
SetCompositeType(const CompositeOperation & type)183 void CanvasRenderingContext2DModelImpl::SetCompositeType(const CompositeOperation& type)
184 {
185 CHECK_NULL_VOID(pattern_);
186 pattern_->UpdateCompositeOperation(type);
187 }
188
SetLineDashOffset(double lineDashOffset)189 void CanvasRenderingContext2DModelImpl::SetLineDashOffset(double lineDashOffset)
190 {
191 CHECK_NULL_VOID(pattern_);
192 pattern_->UpdateLineDashOffset(lineDashOffset);
193 }
194
SetShadowBlur(double blur)195 void CanvasRenderingContext2DModelImpl::SetShadowBlur(double blur)
196 {
197 CHECK_NULL_VOID(pattern_);
198 pattern_->UpdateShadowBlur(blur);
199 }
200
SetShadowColor(const Color & color)201 void CanvasRenderingContext2DModelImpl::SetShadowColor(const Color& color)
202 {
203 CHECK_NULL_VOID(pattern_);
204 pattern_->UpdateShadowColor(color);
205 }
206
SetShadowOffsetX(double offsetX)207 void CanvasRenderingContext2DModelImpl::SetShadowOffsetX(double offsetX)
208 {
209 CHECK_NULL_VOID(pattern_);
210 pattern_->UpdateShadowOffsetX(offsetX);
211 }
212
SetShadowOffsetY(double offsetY)213 void CanvasRenderingContext2DModelImpl::SetShadowOffsetY(double offsetY)
214 {
215 CHECK_NULL_VOID(pattern_);
216 pattern_->UpdateShadowOffsetY(offsetY);
217 }
218
SetSmoothingEnabled(bool enabled)219 void CanvasRenderingContext2DModelImpl::SetSmoothingEnabled(bool enabled)
220 {
221 CHECK_NULL_VOID(pattern_);
222 pattern_->UpdateSmoothingEnabled(enabled);
223 }
224
SetSmoothingQuality(const std::string & quality)225 void CanvasRenderingContext2DModelImpl::SetSmoothingQuality(const std::string& quality)
226 {
227 CHECK_NULL_VOID(pattern_);
228 pattern_->UpdateSmoothingQuality(quality);
229 }
230
MoveTo(double x,double y)231 void CanvasRenderingContext2DModelImpl::MoveTo(double x, double y)
232 {
233 CHECK_NULL_VOID(pattern_);
234 pattern_->MoveTo(x, y);
235 }
236
LineTo(double x,double y)237 void CanvasRenderingContext2DModelImpl::LineTo(double x, double y)
238 {
239 CHECK_NULL_VOID(pattern_);
240 pattern_->LineTo(x, y);
241 }
242
BezierCurveTo(const BezierCurveParam & param)243 void CanvasRenderingContext2DModelImpl::BezierCurveTo(const BezierCurveParam& param)
244 {
245 CHECK_NULL_VOID(pattern_);
246 pattern_->BezierCurveTo(param);
247 }
248
QuadraticCurveTo(const QuadraticCurveParam & param)249 void CanvasRenderingContext2DModelImpl::QuadraticCurveTo(const QuadraticCurveParam& param)
250 {
251 CHECK_NULL_VOID(pattern_);
252 pattern_->QuadraticCurveTo(param);
253 }
254
ArcTo(const ArcToParam & param)255 void CanvasRenderingContext2DModelImpl::ArcTo(const ArcToParam& param)
256 {
257 CHECK_NULL_VOID(pattern_);
258 pattern_->ArcTo(param);
259 }
260
Arc(const ArcParam & param)261 void CanvasRenderingContext2DModelImpl::Arc(const ArcParam& param)
262 {
263 CHECK_NULL_VOID(pattern_);
264 pattern_->Arc(param);
265 }
266
Ellipse(const EllipseParam & param)267 void CanvasRenderingContext2DModelImpl::Ellipse(const EllipseParam& param)
268 {
269 CHECK_NULL_VOID(pattern_);
270 pattern_->Ellipse(param);
271 }
272
SetFillRuleForPath(const CanvasFillRule & fillRule)273 void CanvasRenderingContext2DModelImpl::SetFillRuleForPath(const CanvasFillRule& fillRule)
274 {
275 CHECK_NULL_VOID(pattern_);
276 pattern_->UpdateFillRuleForPath(fillRule);
277 pattern_->Fill();
278 }
279
SetFillRuleForPath2D(const CanvasFillRule & fillRule,const RefPtr<CanvasPath2D> & path)280 void CanvasRenderingContext2DModelImpl::SetFillRuleForPath2D(
281 const CanvasFillRule& fillRule, const RefPtr<CanvasPath2D>& path)
282 {
283 CHECK_NULL_VOID(pattern_);
284 pattern_->UpdateFillRuleForPath2D(fillRule);
285 pattern_->Fill(path);
286 }
287
SetStrokeRuleForPath2D(const CanvasFillRule & fillRule,const RefPtr<CanvasPath2D> & path)288 void CanvasRenderingContext2DModelImpl::SetStrokeRuleForPath2D(
289 const CanvasFillRule& fillRule, const RefPtr<CanvasPath2D>& path)
290 {
291 CHECK_NULL_VOID(pattern_);
292 pattern_->UpdateFillRuleForPath2D(fillRule);
293 pattern_->Stroke(path);
294 }
295
SetStrokeRuleForPath(const CanvasFillRule & fillRule)296 void CanvasRenderingContext2DModelImpl::SetStrokeRuleForPath(const CanvasFillRule& fillRule)
297 {
298 CHECK_NULL_VOID(pattern_);
299 pattern_->UpdateFillRuleForPath(fillRule);
300 pattern_->Stroke();
301 }
302
SetClipRuleForPath(const CanvasFillRule & fillRule)303 void CanvasRenderingContext2DModelImpl::SetClipRuleForPath(const CanvasFillRule& fillRule)
304 {
305 CHECK_NULL_VOID(pattern_);
306 pattern_->UpdateFillRuleForPath(fillRule);
307 pattern_->Clip();
308 }
309
SetClipRuleForPath2D(const CanvasFillRule & fillRule,const RefPtr<CanvasPath2D> & path)310 void CanvasRenderingContext2DModelImpl::SetClipRuleForPath2D(
311 const CanvasFillRule& fillRule, const RefPtr<CanvasPath2D>& path)
312 {
313 CHECK_NULL_VOID(pattern_);
314 pattern_->UpdateFillRuleForPath2D(fillRule);
315 pattern_->Clip(path);
316 }
317
AddRect(const Rect & rect)318 void CanvasRenderingContext2DModelImpl::AddRect(const Rect& rect)
319 {
320 CHECK_NULL_VOID(pattern_);
321 pattern_->AddRect(rect);
322 }
323
BeginPath()324 void CanvasRenderingContext2DModelImpl::BeginPath()
325 {
326 CHECK_NULL_VOID(pattern_);
327 pattern_->BeginPath();
328 }
329
ClosePath()330 void CanvasRenderingContext2DModelImpl::ClosePath()
331 {
332 CHECK_NULL_VOID(pattern_);
333 pattern_->ClosePath();
334 }
335
Restore()336 void CanvasRenderingContext2DModelImpl::Restore()
337 {
338 CHECK_NULL_VOID(pattern_);
339 pattern_->Restore();
340 }
341
CanvasRendererSave()342 void CanvasRenderingContext2DModelImpl::CanvasRendererSave()
343 {
344 CHECK_NULL_VOID(pattern_);
345 pattern_->Save();
346 }
347
CanvasRendererRotate(double angle)348 void CanvasRenderingContext2DModelImpl::CanvasRendererRotate(double angle)
349 {
350 CHECK_NULL_VOID(pattern_);
351 pattern_->Rotate(angle);
352 }
353
CanvasRendererScale(double x,double y)354 void CanvasRenderingContext2DModelImpl::CanvasRendererScale(double x, double y)
355 {
356 CHECK_NULL_VOID(pattern_);
357 pattern_->Scale(x, y);
358 }
359
SetTransform(TransformParam & param,bool lengthFlag)360 void CanvasRenderingContext2DModelImpl::SetTransform(TransformParam& param, bool lengthFlag)
361 {
362 if (!lengthFlag) {
363 return;
364 }
365 std::swap(param.skewX, param.skewY);
366
367 CHECK_NULL_VOID(pattern_);
368 pattern_->SetTransform(param);
369 }
370
ResetTransform()371 void CanvasRenderingContext2DModelImpl::ResetTransform()
372 {
373 CHECK_NULL_VOID(pattern_);
374 pattern_->ResetTransform();
375 }
376
Transform(const TransformParam & param)377 void CanvasRenderingContext2DModelImpl::Transform(const TransformParam& param)
378 {
379 CHECK_NULL_VOID(pattern_);
380 pattern_->Transform(param);
381 }
382
Translate(double x,double y)383 void CanvasRenderingContext2DModelImpl::Translate(double x, double y)
384 {
385 CHECK_NULL_VOID(pattern_);
386 pattern_->Translate(x, y);
387 }
388
SetLineDash(const std::vector<double> & lineDash)389 void CanvasRenderingContext2DModelImpl::SetLineDash(const std::vector<double>& lineDash)
390 {
391 CHECK_NULL_VOID(pattern_);
392 pattern_->UpdateLineDash(lineDash);
393 }
394
SetTextAlign(const TextAlign & align)395 void CanvasRenderingContext2DModelImpl::SetTextAlign(const TextAlign& align)
396 {
397 CHECK_NULL_VOID(pattern_);
398 pattern_->UpdateTextAlign(align);
399 }
400
SetTextBaseline(const TextBaseline & baseline)401 void CanvasRenderingContext2DModelImpl::SetTextBaseline(const TextBaseline& baseline)
402 {
403 CHECK_NULL_VOID(pattern_);
404 pattern_->UpdateTextBaseline(baseline);
405 }
406
GetMeasureTextWidth(const PaintState & state,const std::string & text)407 double CanvasRenderingContext2DModelImpl::GetMeasureTextWidth(const PaintState& state, const std::string& text)
408 {
409 return pattern_ ? pattern_->MeasureText(text, state) : 0.0;
410 }
411
GetMeasureTextHeight(const PaintState & state,const std::string & text)412 double CanvasRenderingContext2DModelImpl::GetMeasureTextHeight(const PaintState& state, const std::string& text)
413 {
414 return pattern_ ? pattern_->MeasureTextHeight(text, state) : 0.0;
415 }
416
FillRect(const Rect & rect)417 void CanvasRenderingContext2DModelImpl::FillRect(const Rect& rect)
418 {
419 CHECK_NULL_VOID(pattern_);
420 pattern_->FillRect(rect);
421 }
422
StrokeRect(const Rect & rect)423 void CanvasRenderingContext2DModelImpl::StrokeRect(const Rect& rect)
424 {
425 CHECK_NULL_VOID(pattern_);
426 pattern_->StrokeRect(rect);
427 }
428
ClearRect(const Rect & rect)429 void CanvasRenderingContext2DModelImpl::ClearRect(const Rect& rect)
430 {
431 CHECK_NULL_VOID(pattern_);
432 pattern_->ClearRect(rect);
433 }
434
DrawBitmapMesh(const BitmapMeshInfo & bitmapMeshInfo)435 void CanvasRenderingContext2DModelImpl::DrawBitmapMesh(const BitmapMeshInfo& bitmapMeshInfo)
436 {
437 CHECK_NULL_VOID(bitmapMeshInfo.pool);
438 auto pool = AceType::DynamicCast<CanvasTaskPool>(bitmapMeshInfo.pool);
439 CHECK_NULL_VOID(pool);
440 CHECK_NULL_VOID(bitmapMeshInfo.offscreenPattern);
441 auto offscreenPattern = AceType::DynamicCast<OffscreenCanvas>(bitmapMeshInfo.offscreenPattern);
442 CHECK_NULL_VOID(offscreenPattern);
443 pool->DrawBitmapMesh(offscreenPattern, bitmapMeshInfo.mesh, bitmapMeshInfo.column, bitmapMeshInfo.row);
444 }
445
GetPixelMap(const ImageSize & imageSize)446 RefPtr<Ace::PixelMap> CanvasRenderingContext2DModelImpl::GetPixelMap(const ImageSize& imageSize)
447 {
448 #ifdef PIXEL_MAP_SUPPORTED
449 // 1 Get data from canvas
450 std::unique_ptr<ImageData> canvasData = GetImageData(imageSize);
451 CHECK_NULL_RETURN(canvasData, nullptr);
452
453 uint32_t finalHeight = static_cast<uint32_t>(std::abs(imageSize.height));
454 uint32_t finalWidth = static_cast<uint32_t>(std::abs(imageSize.width));
455 if (finalHeight > 0 && finalWidth > (UINT32_MAX / finalHeight)) {
456 LOGE("Integer Overflow!!!the product of finalHeight and finalWidth is too big.");
457 return nullptr;
458 }
459 uint32_t length = finalHeight * finalWidth;
460 uint32_t* data = new uint32_t[length];
461 for (uint32_t i = 0; i < finalHeight; i++) {
462 for (uint32_t j = 0; j < finalWidth; j++) {
463 uint32_t idx = i * finalWidth + j;
464 data[idx] = canvasData->data[idx];
465 }
466 }
467
468 // 2 Create pixelmap
469 OHOS::Media::InitializationOptions options;
470 options.alphaType = OHOS::Media::AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
471 options.pixelFormat = OHOS::Media::PixelFormat::RGBA_8888;
472 options.scaleMode = OHOS::Media::ScaleMode::CENTER_CROP;
473 options.size.width = static_cast<int32_t>(finalWidth);
474 options.size.height = static_cast<int32_t>(finalHeight);
475 options.editable = true;
476 auto pixelmap = Ace::PixelMap::Create(OHOS::Media::PixelMap::Create(data, length, options));
477 delete[] data;
478 return pixelmap;
479 #else
480 return nullptr;
481 #endif
482 }
483
GetImageDataModel(const ImageSize & imageSize,uint8_t * buffer)484 void CanvasRenderingContext2DModelImpl::GetImageDataModel(const ImageSize& imageSize, uint8_t* buffer)
485 {
486 auto finalHeight = static_cast<uint32_t>(std::abs(imageSize.height));
487 auto finalWidth = static_cast<uint32_t>(std::abs(imageSize.width));
488 std::unique_ptr<Ace::ImageData> data = GetImageData(imageSize);
489 if (data != nullptr) {
490 for (uint32_t idx = 0; idx < finalHeight * finalWidth; ++idx) {
491 Color color = Color(data->data[idx]);
492 buffer[4 * idx] = color.GetRed(); // 4 * idx: the 1st byte format: red.
493 buffer[4 * idx + 1] = color.GetGreen(); // 4 * idx + 1: the 2nd byte format: green.
494 buffer[4 * idx + 2] = color.GetBlue(); // 4 * idx + 2: the 3rd byte format: blue.
495 buffer[4 * idx + 3] = color.GetAlpha(); // 4 * idx + 3: the 4th byte format: alpha.
496 }
497 }
498 }
499
GetMeasureTextMetrics(const PaintState & state,const std::string & text)500 TextMetrics CanvasRenderingContext2DModelImpl::GetMeasureTextMetrics(const PaintState& state, const std::string& text)
501 {
502 return pattern_ ? pattern_->MeasureTextMetrics(text, state) : TextMetrics {};
503 }
504
505 // All interfaces that only the 'CanvasRenderingContext2D' has.
GetWidth(double & width)506 void CanvasRenderingContext2DModelImpl::GetWidth(double& width)
507 {
508 CHECK_NULL_VOID(pattern_);
509 width = pattern_->GetWidth();
510 }
511
GetHeight(double & height)512 void CanvasRenderingContext2DModelImpl::GetHeight(double& height)
513 {
514 CHECK_NULL_VOID(pattern_);
515 height = pattern_->GetHeight();
516 }
517
SetTransferFromImageBitmap(RefPtr<AceType> offscreenCPattern)518 void CanvasRenderingContext2DModelImpl::SetTransferFromImageBitmap(RefPtr<AceType> offscreenCPattern)
519 {
520 CHECK_NULL_VOID(pattern_);
521 auto offscreenCanvas = AceType::DynamicCast<OffscreenCanvas>(offscreenCPattern);
522 CHECK_NULL_VOID(offscreenCanvas);
523 pattern_->TransferFromImageBitmap(offscreenCanvas);
524 }
525 } // namespace OHOS::Ace::Framework
526