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