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