1 /*
2 * Copyright (c) 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/cj_frontend/cppview/canvas_renderer.h"
17
18 #include <cstdint>
19 #include <string>
20 #include <vector>
21
22 #include "ffi_remote_data.h"
23
24 #include "base/utils/utils.h"
25 #include "bridge/cj_frontend/cppview/canvas_image_data.h"
26 #include "bridge/cj_frontend/cppview/canvas_pattern.h"
27 #include "bridge/cj_frontend/cppview/render_image.h"
28 #include "core/components/common/properties/paint_state.h"
29 #include "core/pipeline/base/constants.h"
30
31 using namespace OHOS;
32
33 namespace OHOS::Ace::Framework {
34 std::unordered_map<int32_t, std::shared_ptr<Pattern>> NativeCanvasRenderer::pattern_;
35 unsigned int NativeCanvasRenderer::patternCount_ = 0;
36 namespace {
37 const int EVEN_CHECK = 2;
38 constexpr int32_t ALPHA_INDEX = 3;
39 constexpr uint32_t PIXEL_SIZE = 4;
40 constexpr double DIFF = 1e-10;
41 const std::set<std::string> QUALITY_TYPE = { "low", "medium", "high" }; // Default value is low.
42 } // namespace
43
NativeCanvasRenderer(bool antialias)44 NativeCanvasRenderer::NativeCanvasRenderer(bool antialias) : FFIData()
45 {
46 renderingContext2DModel_ = AceType::MakeRefPtr<NG::CanvasRenderingContext2DModelNG>();
47 antialias_ = antialias;
48 density_ = PipelineBase::GetCurrentDensity();
49 }
50
NativeCanvasRenderer()51 NativeCanvasRenderer::NativeCanvasRenderer() : FFIData()
52 {
53 renderingContext2DModel_ = AceType::MakeRefPtr<NG::CanvasRenderingContext2DModelNG>();
54 density_ = PipelineBase::GetCurrentDensity();
55 }
56
~NativeCanvasRenderer()57 NativeCanvasRenderer::~NativeCanvasRenderer()
58 {
59 LOGI("Native CanvasRenderer Destroyed: %{public}" PRId64, GetID());
60 }
61
SetCanvasPattern(const RefPtr<AceType> & canvas)62 void NativeCanvasRenderer::SetCanvasPattern(const RefPtr<AceType>& canvas)
63 {
64 canvasPattern_ = canvas;
65 renderingContext2DModel_->SetPattern(canvas);
66 if (isInitializeShadow_) {
67 return;
68 }
69 isInitializeShadow_ = true;
70 renderingContext2DModel_->SetShadowColor(Color::TRANSPARENT);
71 }
72
SetAntiAlias()73 void NativeCanvasRenderer::SetAntiAlias()
74 {
75 renderingContext2DModel_->SetAntiAlias(antialias_);
76 }
77
MakePath2D(const std::string & capStr)78 RefPtr<CanvasPath2D> NativeCanvasRenderer::MakePath2D(const std::string& capStr)
79 {
80 return AceType::MakeRefPtr<CanvasPath2D>(capStr);
81 }
82
SetFillStyle(const Color & color)83 void NativeCanvasRenderer::SetFillStyle(const Color& color)
84 {
85 renderingContext2DModel_->SetFillColor(color, true);
86 }
87
SetFillStyle(const sptr<NativeCanvasGradient> & nativeCanvasGradient)88 void NativeCanvasRenderer::SetFillStyle(const sptr<NativeCanvasGradient>& nativeCanvasGradient)
89 {
90 auto gradient = std::make_shared<Gradient>(nativeCanvasGradient->GetGradient());
91 renderingContext2DModel_->SetFillGradient(gradient);
92 }
93
SetFillStyle(const sptr<NativeCanvasPattern> & nativeCanvasPattern)94 void NativeCanvasRenderer::SetFillStyle(const sptr<NativeCanvasPattern>& nativeCanvasPattern)
95 {
96 auto id = nativeCanvasPattern->GetId();
97 renderingContext2DModel_->SetFillPattern(GetPatternPtr(id));
98 }
99
SetLineWidth(const double lineWidth)100 void NativeCanvasRenderer::SetLineWidth(const double lineWidth)
101 {
102 renderingContext2DModel_->SetLineWidth(lineWidth * GetDensity());
103 }
104
SetStrokeStyle(const Color & color)105 void NativeCanvasRenderer::SetStrokeStyle(const Color& color)
106 {
107 renderingContext2DModel_->SetStrokeColor(color, true);
108 }
109
SetStrokeStyle(const sptr<NativeCanvasGradient> & nativeCanvasGradient)110 void NativeCanvasRenderer::SetStrokeStyle(const sptr<NativeCanvasGradient>& nativeCanvasGradient)
111 {
112 auto gradient = std::make_shared<Gradient>(nativeCanvasGradient->GetGradient());
113 renderingContext2DModel_->SetStrokeGradient(gradient);
114 }
115
SetStrokeStyle(const sptr<NativeCanvasPattern> & nativeCanvasPattern)116 void NativeCanvasRenderer::SetStrokeStyle(const sptr<NativeCanvasPattern>& nativeCanvasPattern)
117 {
118 auto id = nativeCanvasPattern->GetId();
119 renderingContext2DModel_->SetStrokePattern(GetPatternPtr(id));
120 }
121
SetLineCap(const LineCapStyle lineCap)122 void NativeCanvasRenderer::SetLineCap(const LineCapStyle lineCap)
123 {
124 renderingContext2DModel_->SetLineCap(lineCap);
125 }
126
SetLineJoin(const LineJoinStyle lineJoin)127 void NativeCanvasRenderer::SetLineJoin(const LineJoinStyle lineJoin)
128 {
129 renderingContext2DModel_->SetLineJoin(lineJoin);
130 }
131
SetMiterLimit(double limit)132 void NativeCanvasRenderer::SetMiterLimit(double limit)
133 {
134 renderingContext2DModel_->SetMiterLimit(limit * GetDensity());
135 }
136
SetFont(const FontStyle fontStyle,const std::string & fontWeight,const Dimension & fontSize,const std::string & fontFamily)137 void NativeCanvasRenderer::SetFont(
138 const FontStyle fontStyle, const std::string& fontWeight, const Dimension& fontSize, const std::string& fontFamily)
139 {
140 auto weight = ConvertStrToFontWeight(fontWeight);
141 auto families = ConvertStrToFontFamilies(fontFamily);
142
143 renderingContext2DModel_->SetFontStyle(fontStyle);
144 renderingContext2DModel_->SetFontWeight(weight);
145 renderingContext2DModel_->SetFontSize(fontSize);
146 renderingContext2DModel_->SetFontFamilies(families);
147
148 paintState_.SetFontWeight(weight);
149 paintState_.SetFontStyle(fontStyle);
150 paintState_.SetFontFamilies(families);
151 paintState_.SetFontSize(fontSize);
152 style_.SetFontStyle(fontStyle);
153 style_.SetFontWeight(weight);
154 style_.SetFontSize(fontSize);
155 style_.SetFontFamilies(families);
156 }
157
SetTextAlign(const TextAlign align)158 void NativeCanvasRenderer::SetTextAlign(const TextAlign align)
159 {
160 paintState_.SetTextAlign(align);
161 renderingContext2DModel_->SetTextAlign(align);
162 }
163
SetTextBaseline(const TextBaseline baseline)164 void NativeCanvasRenderer::SetTextBaseline(const TextBaseline baseline)
165 {
166 paintState_.SetTextBaseline(baseline);
167 renderingContext2DModel_->SetTextBaseline(baseline);
168 style_.SetTextBaseline(baseline);
169 }
170
SetGlobalAlpha(double alpha)171 void NativeCanvasRenderer::SetGlobalAlpha(double alpha)
172 {
173 renderingContext2DModel_->SetGlobalAlpha(alpha);
174 }
175
SetLineDash(std::vector<double> & lineDash)176 void NativeCanvasRenderer::SetLineDash(std::vector<double>& lineDash)
177 {
178 if (lineDash.size() % EVEN_CHECK != 0) {
179 lineDash.insert(lineDash.end(), lineDash.begin(), lineDash.end());
180 }
181 double density = GetDensity();
182 for (auto i = 0U; i < lineDash.size(); i++) {
183 lineDash[i] *= density;
184 }
185 renderingContext2DModel_->SetLineDash(lineDash);
186 }
187
GetLineDash()188 std::vector<double> NativeCanvasRenderer::GetLineDash()
189 {
190 std::vector<double> lineDash = renderingContext2DModel_->GetLineDash();
191 double density = !NearZero(GetDensity()) ? GetDensity() : 1.0;
192 for (auto i = 0U; i < lineDash.size(); i++) {
193 lineDash[i] /= density;
194 }
195 return lineDash;
196 }
197
SetLineDashOffset(const double lineDashOffset)198 void NativeCanvasRenderer::SetLineDashOffset(const double lineDashOffset)
199 {
200 renderingContext2DModel_->SetLineDashOffset(lineDashOffset * GetDensity());
201 }
202
SetGlobalCompositeOperation(const CompositeOperation type)203 void NativeCanvasRenderer::SetGlobalCompositeOperation(const CompositeOperation type)
204 {
205 renderingContext2DModel_->SetCompositeType(type);
206 }
207
SetShadowBlur(const double blur)208 void NativeCanvasRenderer::SetShadowBlur(const double blur)
209 {
210 renderingContext2DModel_->SetShadowBlur(blur);
211 }
212
SetShadowColor(const Color & color)213 void NativeCanvasRenderer::SetShadowColor(const Color& color)
214 {
215 renderingContext2DModel_->SetShadowColor(color);
216 }
217
SetShadowOffsetX(const double offsetX)218 void NativeCanvasRenderer::SetShadowOffsetX(const double offsetX)
219 {
220 renderingContext2DModel_->SetShadowOffsetX(offsetX * GetDensity());
221 }
222
SetShadowOffsetY(const double offsetY)223 void NativeCanvasRenderer::SetShadowOffsetY(const double offsetY)
224 {
225 renderingContext2DModel_->SetShadowOffsetX(offsetY * GetDensity());
226 }
227
SetImageSmoothingEnabled(const bool enabled)228 void NativeCanvasRenderer::SetImageSmoothingEnabled(const bool enabled)
229 {
230 renderingContext2DModel_->SetSmoothingEnabled(enabled);
231 }
232
SetImageSmoothingQuality(const std::string & quality)233 void NativeCanvasRenderer::SetImageSmoothingQuality(const std::string& quality)
234 {
235 if ((QUALITY_TYPE.find(quality) != QUALITY_TYPE.end())) {
236 renderingContext2DModel_->SetSmoothingQuality(quality);
237 } else {
238 LOGE("canvas error: Wrong quality");
239 }
240 }
241
ToDataURL(const std::string & dataUrl,double quality)242 std::string NativeCanvasRenderer::ToDataURL(const std::string& dataUrl, double quality)
243 {
244 std::string result = renderingContext2DModel_->ToDataURL(dataUrl, quality);
245 return result;
246 }
247
FillRect(const Rect & rect)248 void NativeCanvasRenderer::FillRect(const Rect& rect)
249 {
250 renderingContext2DModel_->FillRect(rect * GetDensity());
251 }
252
StrokeRect(const Rect & rect)253 void NativeCanvasRenderer::StrokeRect(const Rect& rect)
254 {
255 renderingContext2DModel_->StrokeRect(rect * GetDensity());
256 }
257
ClearRect(const Rect & rect)258 void NativeCanvasRenderer::ClearRect(const Rect& rect)
259 {
260 renderingContext2DModel_->ClearRect(rect * GetDensity());
261 }
262
FillText(const double x,const double y,const std::string & text)263 void NativeCanvasRenderer::FillText(const double x, const double y, const std::string& text)
264 {
265 double density = GetDensity();
266 FillTextInfo textInfo;
267 textInfo.text = text;
268 textInfo.x = x * density;
269 textInfo.y = y * density;
270 renderingContext2DModel_->SetFillText(paintState_, textInfo);
271 }
272
FillText(double x,double y,const std::string & text,double maxWidth)273 void NativeCanvasRenderer::FillText(double x, double y, const std::string& text, double maxWidth)
274 {
275 double density = GetDensity();
276 FillTextInfo textInfo;
277 textInfo.text = text;
278 textInfo.x = x * density;
279 textInfo.y = y * density;
280 textInfo.maxWidth = maxWidth * density;
281 renderingContext2DModel_->SetFillText(paintState_, textInfo);
282 }
283
StrokeText(const double x,const double y,const std::string & text)284 void NativeCanvasRenderer::StrokeText(const double x, const double y, const std::string& text)
285 {
286 FillTextInfo textInfo;
287 double density = GetDensity();
288 textInfo.text = text;
289 textInfo.x = x * density;
290 textInfo.y = y * density;
291 renderingContext2DModel_->SetStrokeText(paintState_, textInfo);
292 }
293
StrokeText(double x,double y,const std::string & text,double maxWidth)294 void NativeCanvasRenderer::StrokeText(double x, double y, const std::string& text, double maxWidth)
295 {
296 FillTextInfo textInfo;
297 double density = GetDensity();
298 textInfo.text = text;
299 textInfo.x = x * density;
300 textInfo.y = y * density;
301 textInfo.maxWidth = maxWidth * density;
302 renderingContext2DModel_->SetStrokeText(paintState_, textInfo);
303 }
304
MeasureText(const std::string & text)305 Metrics NativeCanvasRenderer::MeasureText(const std::string& text)
306 {
307 paintState_.SetTextStyle(style_);
308
309 double density = Positive(GetDensity()) ? GetDensity() : 1;
310 TextMetrics textMetrics = renderingContext2DModel_->GetMeasureTextMetrics(paintState_, text);
311 if (NearZero(density)) {
312 density = 1.0;
313 }
314 double width = textMetrics.width / density;
315 double height = textMetrics.height / density;
316 double actualBoundingBoxLeft = textMetrics.actualBoundingBoxLeft / density;
317 double actualBoundingBoxRight = textMetrics.actualBoundingBoxRight / density;
318 double actualBoundingBoxAscent = textMetrics.actualBoundingBoxAscent / density;
319 double actualBoundingBoxDescent = textMetrics.actualBoundingBoxDescent / density;
320 double alphabeticBaseline = textMetrics.alphabeticBaseline / density;
321 double emHeightAscent = textMetrics.emHeightAscent / density;
322 double emHeightDescent = textMetrics.emHeightDescent / density;
323 double fontBoundingBoxAscent = textMetrics.fontBoundingBoxAscent / density;
324 double fontBoundingBoxDescent = textMetrics.fontBoundingBoxDescent / density;
325 double hangingBaseline = textMetrics.hangingBaseline / density;
326 double ideographicBaseline = textMetrics.ideographicBaseline / density;
327
328 Metrics metrics = { width, height, actualBoundingBoxLeft, actualBoundingBoxRight, actualBoundingBoxAscent,
329 actualBoundingBoxDescent, alphabeticBaseline, emHeightAscent, emHeightDescent, fontBoundingBoxAscent,
330 fontBoundingBoxDescent, hangingBaseline, ideographicBaseline };
331 return metrics;
332 }
333
Stroke()334 void NativeCanvasRenderer::Stroke()
335 {
336 auto fillRule = CanvasFillRule::NONZERO;
337 renderingContext2DModel_->SetStrokeRuleForPath(fillRule);
338 }
339
Stroke(const sptr<NativeCanvasPath> & canvasPath)340 void NativeCanvasRenderer::Stroke(const sptr<NativeCanvasPath>& canvasPath)
341 {
342 auto path = canvasPath->GetCanvasPath2d();
343 auto fillRule = CanvasFillRule::NONZERO;
344
345 renderingContext2DModel_->SetStrokeRuleForPath2D(fillRule, path);
346 }
347
BeginPath()348 void NativeCanvasRenderer::BeginPath()
349 {
350 renderingContext2DModel_->BeginPath();
351 }
352
MoveTo(const double x,const double y)353 void NativeCanvasRenderer::MoveTo(const double x, const double y)
354 {
355 double density = GetDensity();
356 renderingContext2DModel_->MoveTo(x * density, y * density);
357 }
358
LineTo(const double x,const double y)359 void NativeCanvasRenderer::LineTo(const double x, const double y)
360 {
361 double density = GetDensity();
362 renderingContext2DModel_->LineTo(x * density, y * density);
363 }
364
ClosePath()365 void NativeCanvasRenderer::ClosePath()
366 {
367 renderingContext2DModel_->ClosePath();
368 }
369
BezierCurveTo(const BezierCurveParam & param)370 void NativeCanvasRenderer::BezierCurveTo(const BezierCurveParam& param)
371 {
372 double density = GetDensity();
373 BezierCurveParam beParam;
374 beParam.cp1x = param.cp1x * density;
375 beParam.cp1y = param.cp1y * density;
376 beParam.cp2x = param.cp2x * density;
377 beParam.cp2y = param.cp2y * density;
378 beParam.x = param.x * density;
379 beParam.y = param.y * density;
380 renderingContext2DModel_->BezierCurveTo(beParam);
381 }
382
QuadraticCurveTo(const QuadraticCurveParam & param)383 void NativeCanvasRenderer::QuadraticCurveTo(const QuadraticCurveParam& param)
384 {
385 double density = GetDensity();
386 QuadraticCurveParam quParam;
387 quParam.cpx = param.cpx * density;
388 quParam.cpy = param.cpy * density;
389 quParam.x = param.x * density;
390 quParam.y = param.y * density;
391 renderingContext2DModel_->QuadraticCurveTo(quParam);
392 }
393
Arc(const ArcParam & param)394 void NativeCanvasRenderer::Arc(const ArcParam& param)
395 {
396 ArcParam arcParam = param;
397 double density = GetDensity();
398 arcParam.x = param.x * density;
399 arcParam.y = param.y * density;
400 arcParam.radius = param.radius * density;
401 renderingContext2DModel_->Arc(arcParam);
402 }
403
ArcTo(const ArcToParam & param)404 void NativeCanvasRenderer::ArcTo(const ArcToParam& param)
405 {
406 ArcToParam arcToParam;
407 double density = GetDensity();
408 arcToParam.x1 = param.x1 * density;
409 arcToParam.y1 = param.y1 * density;
410 arcToParam.x2 = param.x2 * density;
411 arcToParam.y2 = param.y2 * density;
412 arcToParam.radius = param.radius * density;
413 renderingContext2DModel_->ArcTo(arcToParam);
414 }
415
Ellipse(const EllipseParam & param)416 void NativeCanvasRenderer::Ellipse(const EllipseParam& param)
417 {
418 EllipseParam elParam = param;
419 double density = GetDensity();
420 elParam.x = param.x * density;
421 elParam.y = param.y * density;
422 elParam.radiusX = param.radiusX * density;
423 elParam.radiusY = param.radiusY * density;
424 renderingContext2DModel_->Ellipse(elParam);
425 }
426
SaveLayer()427 void NativeCanvasRenderer::SaveLayer()
428 {
429 renderingContext2DModel_->SaveLayer();
430 }
431
NormalRect(const Rect & rect)432 void NativeCanvasRenderer::NormalRect(const Rect& rect)
433 {
434 renderingContext2DModel_->AddRect(rect * GetDensity());
435 }
436
Fill()437 void NativeCanvasRenderer::Fill()
438 {
439 auto fillRule = CanvasFillRule::NONZERO;
440
441 renderingContext2DModel_->SetFillRuleForPath(fillRule);
442 }
443
Fill(const std::string & ruleStr)444 void NativeCanvasRenderer::Fill(const std::string& ruleStr)
445 {
446 auto fillRule = ruleStr == "evenodd" ? CanvasFillRule::EVENODD : CanvasFillRule::NONZERO;
447 renderingContext2DModel_->SetFillRuleForPath(fillRule);
448 return;
449 }
450
Fill(const sptr<NativeCanvasPath> & canvasPath,const std::string & ruleStr)451 void NativeCanvasRenderer::Fill(const sptr<NativeCanvasPath>& canvasPath, const std::string& ruleStr)
452 {
453 auto fillRule = ruleStr == "evenodd" ? CanvasFillRule::EVENODD : CanvasFillRule::NONZERO;
454 auto path = canvasPath->GetCanvasPath2d();
455 renderingContext2DModel_->SetFillRuleForPath2D(fillRule, path);
456 }
457
Clip()458 void NativeCanvasRenderer::Clip()
459 {
460 auto fillRule = CanvasFillRule::NONZERO;
461 renderingContext2DModel_->SetClipRuleForPath(fillRule);
462 }
463
Clip(const std::string & ruleStr)464 void NativeCanvasRenderer::Clip(const std::string& ruleStr)
465 {
466 auto fillRule = ruleStr == "evenodd" ? CanvasFillRule::EVENODD : CanvasFillRule::NONZERO;
467 renderingContext2DModel_->SetClipRuleForPath(fillRule);
468 return;
469 }
470
Clip(const sptr<NativeCanvasPath> & canvasPath,const std::string & ruleStr)471 void NativeCanvasRenderer::Clip(const sptr<NativeCanvasPath>& canvasPath, const std::string& ruleStr)
472 {
473 auto fillRule = ruleStr == "evenodd" ? CanvasFillRule::EVENODD : CanvasFillRule::NONZERO;
474 auto path = canvasPath->GetCanvasPath2d();
475 renderingContext2DModel_->SetClipRuleForPath2D(fillRule, path);
476 }
477
Rotate(const double angle)478 void NativeCanvasRenderer::Rotate(const double angle)
479 {
480 renderingContext2DModel_->CanvasRendererRotate(angle);
481 }
482
Scale(const double x,const double y)483 void NativeCanvasRenderer::Scale(const double x, const double y)
484 {
485 renderingContext2DModel_->CanvasRendererScale(x, y);
486 }
487
Transform(const TransformParam & param)488 void NativeCanvasRenderer::Transform(const TransformParam& param)
489 {
490 renderingContext2DModel_->Transform(param);
491 }
492
SetTransform(TransformParam param)493 void NativeCanvasRenderer::SetTransform(TransformParam param)
494 {
495 double density = GetDensity();
496 param.translateX *= density;
497 param.translateY *= density;
498 renderingContext2DModel_->SetTransform(param, true);
499 }
500
SetTransform(unsigned int id,const TransformParam & transform)501 void NativeCanvasRenderer::SetTransform(unsigned int id, const TransformParam& transform)
502 {
503 if (id >= 0 && id <= patternCount_) {
504 renderingContext2DModel_->SetTransform(pattern_[id], transform);
505 }
506 }
507
SetTransformByMatrix(const sptr<NativeMatrix2d> & matrix2d)508 void NativeCanvasRenderer::SetTransformByMatrix(const sptr<NativeMatrix2d>& matrix2d)
509 {
510 TransformParam param = matrix2d->GetTransform();
511 renderingContext2DModel_->SetTransform(param, false);
512 }
513
ResetTransform()514 void NativeCanvasRenderer::ResetTransform()
515 {
516 renderingContext2DModel_->ResetTransform();
517 }
518
Translate(const double x,const double y)519 void NativeCanvasRenderer::Translate(const double x, const double y)
520 {
521 double density = GetDensity();
522 renderingContext2DModel_->Translate(x * density, y * density);
523 }
524
Restore()525 void NativeCanvasRenderer::Restore()
526 {
527 if (!savePaintState_.empty()) {
528 paintState_ = savePaintState_.back();
529 savePaintState_.pop_back();
530 }
531 renderingContext2DModel_->Restore();
532 }
533
Save()534 void NativeCanvasRenderer::Save()
535 {
536 savePaintState_.push_back(paintState_);
537 renderingContext2DModel_->CanvasRendererSave();
538 }
539
CreateLinearGradient(const double x0,const double y0,const double x1,const double y1)540 int64_t NativeCanvasRenderer::CreateLinearGradient(const double x0, const double y0, const double x1, const double y1)
541 {
542 double density = GetDensity();
543 Offset beginOffset = Offset(x0 * density, y0 * density);
544 Offset endOffset = Offset(x1 * density, y1 * density);
545
546 Gradient gradient = Gradient();
547 gradient.SetType(GradientType::LINEAR);
548 gradient.SetBeginOffset(beginOffset);
549 gradient.SetEndOffset(endOffset);
550
551 auto nativeCanvasGradient = FFIData::Create<NativeCanvasGradient>(gradient);
552 if (nativeCanvasGradient == nullptr) {
553 return FFI_ERROR_CODE;
554 }
555 return nativeCanvasGradient->GetID();
556 }
557
CreateRadialGradient(const double x0,const double y0,const double r0,const double x1,const double y1,const double r1)558 int64_t NativeCanvasRenderer::CreateRadialGradient(
559 const double x0, const double y0, const double r0, const double x1, const double y1, const double r1)
560 {
561 double density = GetDensity();
562 Offset innerCenter = Offset(x0 * density, y0 * density);
563 Offset outerCenter = Offset(x1 * density, y1 * density);
564
565 Gradient gradient = Gradient();
566 gradient.SetType(GradientType::RADIAL);
567 gradient.SetBeginOffset(innerCenter);
568 gradient.SetEndOffset(outerCenter);
569 gradient.SetInnerRadius(r0 * density);
570 gradient.SetOuterRadius(r1 * density);
571
572 auto nativeCanvasGradient = FFIData::Create<NativeCanvasGradient>(gradient);
573 if (nativeCanvasGradient == nullptr) {
574 return FFI_ERROR_CODE;
575 }
576 return nativeCanvasGradient->GetID();
577 }
578
CreateConicGradient(const double startAngle,const double x,const double y)579 int64_t NativeCanvasRenderer::CreateConicGradient(const double startAngle, const double x, const double y)
580 {
581 double density = GetDensity();
582 Gradient gradient = Gradient();
583 gradient.SetType(GradientType::CONIC);
584 gradient.GetConicGradient().startAngle = AnimatableDimension(Dimension(fmod(startAngle, (EVEN_CHECK * ACE_PI))));
585 gradient.GetConicGradient().centerX = AnimatableDimension(Dimension(x * density));
586 gradient.GetConicGradient().centerY = AnimatableDimension(Dimension(y * density));
587
588 auto nativeCanvasGradient = FFIData::Create<NativeCanvasGradient>(gradient);
589 if (nativeCanvasGradient == nullptr) {
590 return FFI_ERROR_CODE;
591 }
592 return nativeCanvasGradient->GetID();
593 }
594
DrawImage(const CanvasImage & image)595 void NativeCanvasRenderer::DrawImage(const CanvasImage& image)
596 {
597 ImageInfo imageInfo;
598 imageInfo.image = image;
599 imageInfo.isImage = true;
600 renderingContext2DModel_->DrawImage(imageInfo);
601 }
602
DrawImage(const RefPtr<OHOS::Ace::PixelMap> & pixelMap,const CanvasImage & image)603 void NativeCanvasRenderer::DrawImage(const RefPtr<OHOS::Ace::PixelMap>& pixelMap, const CanvasImage& image)
604 {
605 ImageInfo imageInfo;
606 imageInfo.image = image;
607 imageInfo.isImage = false;
608 imageInfo.pixelMap = pixelMap;
609 renderingContext2DModel_->DrawPixelMap(imageInfo);
610 }
611
GetImageData(const double left,const double top,const double width,const double height)612 std::unique_ptr<ImageData> NativeCanvasRenderer::GetImageData(
613 const double left, const double top, const double width, const double height)
614 {
615 std::unique_ptr<ImageData> canvasData;
616 ImageSize imageSize;
617 imageSize.left = left;
618 imageSize.top = top;
619 imageSize.width = width;
620 imageSize.height = height;
621 canvasData = renderingContext2DModel_->GetImageData(imageSize);
622 return canvasData;
623 }
624
GetNativeImageData(const double left,const double top,const double width,const double height)625 int64_t NativeCanvasRenderer::GetNativeImageData(
626 const double left, const double top, const double width, const double height)
627 {
628 ImageSize imageSize;
629 double density = GetDensity();
630 imageSize.left = left * density;
631 imageSize.top = top * density;
632 imageSize.width = width * density + DIFF;
633 imageSize.height = height * density + DIFF;
634
635 uint32_t finalWidth = static_cast<uint32_t>(std::abs(imageSize.width));
636 uint32_t finalHeight = static_cast<uint32_t>(std::abs(imageSize.height));
637 int32_t length = static_cast<int32_t>(finalHeight * finalWidth * 4);
638 std::vector<uint8_t> buffer(length, 0xff);
639 auto imagdata = FFI::FFIData::Create<NativeImageData>();
640 if (finalHeight > 0 && finalWidth > (UINT32_MAX / finalHeight)) {
641 imagdata->height_ = 0;
642 imagdata->width_ = 0;
643 imagdata->data = buffer;
644 return imagdata->GetID();
645 }
646 renderingContext2DModel_->GetImageDataModel(imageSize, buffer.data());
647 imagdata->height_ = static_cast<int32_t>(finalHeight);
648 imagdata->width_ = static_cast<int32_t>(finalWidth);
649 imagdata->data = buffer;
650 return imagdata->GetID();
651 }
652
GetPixelMap(double left,double top,double width,double height)653 int64_t NativeCanvasRenderer::GetPixelMap(double left, double top, double width, double height)
654 {
655 auto finalHeight = static_cast<uint32_t>(std::abs(height));
656 auto finalWidth = static_cast<uint32_t>(std::abs(width));
657 if (finalHeight > 0 && finalWidth > (UINT32_MAX / finalHeight)) {
658 return 0;
659 }
660 double density = GetDensity();
661 ImageSize imageSize;
662 imageSize.left = left * density;
663 imageSize.top = top * density;
664 imageSize.width = finalWidth * density + DIFF;
665 imageSize.height = finalHeight * density + DIFF;
666 finalHeight = static_cast<uint32_t>(std::abs(imageSize.height));
667 finalHeight = static_cast<uint32_t>(std::abs(imageSize.width));
668 if (height > 0 && width > (UINT32_MAX / height)) {
669 LOGE("NativeCanvasRenderer GetPixelMap failed");
670 return 0;
671 }
672 auto pixelmap = renderingContext2DModel_->GetPixelMap(imageSize);
673 if (pixelmap) {
674 auto ret = FFIData::Create<OHOS::Media::PixelMapImpl>(pixelmap->GetPixelMapSharedPtr());
675 if (ret == nullptr) {
676 return FFI_ERROR_CODE;
677 }
678 return ret->GetID();
679 } else {
680 LOGE("NativeCanvasRenderer GetPixelMap failed");
681 return 0;
682 }
683 }
684
SetFilter(const std::string & filterStr)685 void NativeCanvasRenderer::SetFilter(const std::string& filterStr)
686 {
687 renderingContext2DModel_->SetFilterParam(filterStr);
688 }
689
SetDirection(const std::string & directionStr)690 void NativeCanvasRenderer::SetDirection(const std::string& directionStr)
691 {
692 auto direction = ConvertStrToTextDirection(directionStr);
693 renderingContext2DModel_->SetTextDirection(direction);
694 }
695
GetJsonData(const std::string & path)696 std::string NativeCanvasRenderer::GetJsonData(const std::string& path)
697 {
698 std::string jsonData = renderingContext2DModel_->GetJsonData(path);
699 return jsonData;
700 }
701
RestoreLayer()702 void NativeCanvasRenderer::RestoreLayer()
703 {
704 renderingContext2DModel_->RestoreLayer();
705 }
706
Reset()707 void NativeCanvasRenderer::Reset()
708 {
709 paintState_ = PaintState();
710 std::vector<PaintState>().swap(savePaintState_);
711 isInitializeShadow_ = false;
712 renderingContext2DModel_->Reset();
713 }
714
CreatePattern(int64_t bitMapId,const std::string & repeat)715 int64_t NativeCanvasRenderer::CreatePattern(int64_t bitMapId, const std::string& repeat)
716 {
717 auto renderImage = FFIData::GetData<CJRenderImage>(bitMapId);
718 if (renderImage == nullptr) {
719 LOGE("canvas createCanvasPattern error, Cannot get CJRenderImage by id: %{public}" PRId64, bitMapId);
720 return 0;
721 }
722 auto pattern = std::make_shared<Pattern>();
723 pattern->SetImgSrc(renderImage->GetSrc());
724 pattern->SetImageWidth(renderImage->GetWidth());
725 pattern->SetImageHeight(renderImage->GetHeight());
726 pattern->SetRepetition(repeat);
727 #if !defined(PREVIEW)
728 auto pixelMap = renderImage->GetPixelMap();
729 pattern->SetPixelMap(pixelMap);
730 #endif
731
732 pattern_[patternCount_] = pattern;
733 auto nativeCanvasPattern = FFIData::Create<NativeCanvasPattern>();
734 if (nativeCanvasPattern == nullptr) {
735 return FFI_ERROR_CODE;
736 }
737 nativeCanvasPattern->SetCanvasRenderer(this);
738 nativeCanvasPattern->SetId(patternCount_);
739 nativeCanvasPattern->SetUnit(GetUnit());
740 patternCount_++;
741 return nativeCanvasPattern->GetID();
742 }
743
GetPatternPtr(int32_t id)744 std::shared_ptr<Pattern> NativeCanvasRenderer::GetPatternPtr(int32_t id)
745 {
746 if (id < 0 || id >= static_cast<int32_t>(pattern_.size())) {
747 return std::shared_ptr<Pattern>();
748 }
749 return pattern_[id];
750 }
751
GetTransform()752 int64_t NativeCanvasRenderer::GetTransform()
753 {
754 TransformParam param = renderingContext2DModel_->GetTransform();
755 auto nativeMatrix2d = FFIData::Create<NativeMatrix2d>();
756 nativeMatrix2d->SetTransform(param);
757 return nativeMatrix2d->GetID();
758 }
759
SetPixelMap(const RefPtr<OHOS::Ace::PixelMap> & pixelMap)760 void NativeCanvasRenderer::SetPixelMap(const RefPtr<OHOS::Ace::PixelMap>& pixelMap)
761 {
762 #if !defined(PREVIEW)
763 ImageInfo imageInfo;
764 imageInfo.pixelMap = pixelMap;
765 renderingContext2DModel_->DrawPixelMap(imageInfo);
766 #endif
767 }
768
SetDensity()769 void NativeCanvasRenderer::SetDensity()
770 {
771 double density = GetDensity(true);
772 renderingContext2DModel_->SetDensity(density);
773 }
774
ToDataUrl(const std::string type,const double quality)775 std::string NativeCanvasRenderer::ToDataUrl(const std::string type, const double quality)
776 {
777 std::string result = renderingContext2DModel_->ToDataURL(type, quality);
778 return result;
779 }
780
GetWidth()781 double NativeCanvasRenderer::GetWidth()
782 {
783 double width = 0.0;
784 auto canvasRenderingContext2DModel = AceType::DynamicCast<CanvasRenderingContext2DModel>(renderingContext2DModel_);
785 CHECK_NULL_RETURN(canvasRenderingContext2DModel, -1);
786 canvasRenderingContext2DModel->GetWidth(width);
787 double density = !NearZero(GetDensity()) ? GetDensity() : 1.0;
788 width /= density;
789 return width;
790 }
791
GetHeight()792 double NativeCanvasRenderer::GetHeight()
793 {
794 double height = 0.0;
795 auto canvasRenderingContext2DModel = AceType::DynamicCast<CanvasRenderingContext2DModel>(renderingContext2DModel_);
796 CHECK_NULL_RETURN(canvasRenderingContext2DModel, -1);
797 canvasRenderingContext2DModel->GetHeight(height);
798 double density = !NearZero(GetDensity()) ? GetDensity() : 1.0;
799 height /= density;
800 return height;
801 }
802
TransferFromImageBitmap(const sptr<CJRenderImage> cjImage)803 void NativeCanvasRenderer::TransferFromImageBitmap(const sptr<CJRenderImage> cjImage)
804 {
805 auto canvasRenderingContext2DModel = AceType::DynamicCast<CanvasRenderingContext2DModel>(renderingContext2DModel_);
806 CHECK_NULL_VOID(canvasRenderingContext2DModel);
807 #ifdef PIXEL_MAP_SUPPORTED
808 canvasRenderingContext2DModel->TransferFromImageBitmap(cjImage->GetPixelMap());
809 #else
810 auto imageData = cjImage->imageData;
811 CHECK_NULL_VOID(imageData);
812 canvasRenderingContext2DModel->TransferFromImageBitmap(imageData);
813 #endif
814 }
815
CreateImageData(const double height,const double width)816 int64_t NativeCanvasRenderer::CreateImageData(const double height, const double width)
817 {
818 auto imageData = FFIData::Create<NativeImageData>();
819 double density = GetDensity();
820 int32_t finalWidth = static_cast<int32_t>(std::abs(width * density + DIFF));
821 int32_t finalHeight = static_cast<int32_t>(std::abs(height * density + DIFF));
822 int32_t result = finalWidth * finalHeight * PIXEL_SIZE;
823 std::vector<uint8_t> bufferArray;
824 for (int32_t i = 0; i < result; i++) {
825 bufferArray.emplace_back(0xff);
826 }
827 imageData->height_ = finalHeight;
828 imageData->width_ = finalHeight;
829 imageData->data = bufferArray;
830 return imageData->GetID();
831 }
832
CreateImageData(const sptr<NativeImageData> imageData)833 int64_t NativeCanvasRenderer::CreateImageData(const sptr<NativeImageData> imageData)
834 {
835 auto ret = FFIData::Create<NativeImageData>();
836 double density = GetDensity();
837 int32_t finalWidth = static_cast<int32_t>(std::abs(imageData->width_ * density + DIFF));
838 int32_t finalHeight = static_cast<int32_t>(std::abs(imageData->height_ * density + DIFF));
839 int32_t result = finalWidth * finalHeight * PIXEL_SIZE;
840 std::vector<uint8_t> bufferArray;
841 for (int32_t i = 0; i < result; i++) {
842 bufferArray.emplace_back(0xff);
843 }
844 ret->height_ = finalHeight;
845 ret->width_ = finalHeight;
846 ret->data = bufferArray;
847 return ret->GetID();
848 }
849
PutImageData(const sptr<NativeImageData> imageData,const double dx,const double dy,const double dirtyX,const double dirtyY,const double dirtyWidth,const double dirtyHeight)850 void NativeCanvasRenderer::PutImageData(const sptr<NativeImageData> imageData, const double dx, const double dy,
851 const double dirtyX, const double dirtyY, const double dirtyWidth, const double dirtyHeight)
852 {
853 double density = GetDensity();
854 int32_t imgWidth = imageData->GetWidth();
855 int32_t imgHeight = imageData->GetHeight();
856 ImageData imageData_ = { .dirtyWidth = imgWidth, .dirtyHeight = imgHeight };
857 imageData_.x = static_cast<int32_t>(dx * density);
858 imageData_.y = static_cast<int32_t>(dy * density);
859 imageData_.dirtyX = static_cast<int32_t>(dirtyX * density);
860 imageData_.dirtyY = static_cast<int32_t>(dirtyY * density);
861 imageData_.dirtyHeight = static_cast<int32_t>(dirtyHeight * density);
862 imageData_.dirtyWidth = static_cast<int32_t>(dirtyWidth * density);
863 imageData_.dirtyWidth = imageData_.dirtyX < 0 ? std::min(imageData_.dirtyX + imageData_.dirtyWidth, imgWidth)
864 : std::min(imgWidth - imageData_.dirtyX, imageData_.dirtyWidth);
865 imageData_.dirtyHeight = imageData_.dirtyY < 0 ? std::min(imageData_.dirtyY + imageData_.dirtyHeight, imgHeight)
866 : std::min(imgHeight - imageData_.dirtyY, imageData_.dirtyHeight);
867 auto buffer = imageData->data;
868 int32_t bufferLength = static_cast<int32_t>(buffer.size());
869 imageData_.data = std::vector<uint32_t>();
870 for (int32_t i = std::max(imageData_.dirtyY, 0); i < imageData_.dirtyY + imageData_.dirtyHeight; ++i) {
871 for (int32_t j = std::max(imageData_.dirtyX, 0); j < imageData_.dirtyX + imageData_.dirtyWidth; ++j) {
872 uint32_t idx = static_cast<uint32_t>(4 * (j + imgWidth * i));
873 if (bufferLength > static_cast<int32_t>(idx + ALPHA_INDEX)) {
874 uint8_t alpha = buffer[idx + 3]; // idx + 3: The 4th byte format: alpha
875 uint8_t red = buffer[idx]; // idx: the 1st byte format: red
876 uint8_t green = buffer[idx + 1]; // idx + 1: The 2nd byte format: green
877 uint8_t blue = buffer[idx + 2]; // idx + 2: The 3rd byte format: blue
878 imageData_.data.emplace_back(Color::FromARGB(alpha, red, green, blue).GetValue());
879 }
880 }
881 }
882 renderingContext2DModel_->PutImageData(imageData_);
883 }
884
PutImageData(const sptr<NativeImageData> imageData,const double dx,const double dy)885 void NativeCanvasRenderer::PutImageData(const sptr<NativeImageData> imageData, const double dx, const double dy)
886 {
887 double density = GetDensity();
888 int32_t imgWidth = imageData->GetWidth();
889 int32_t imgHeight = imageData->GetHeight();
890 ImageData imageData_ = { .dirtyWidth = imgWidth, .dirtyHeight = imgHeight };
891 imageData_.x = static_cast<int32_t>(dx * density);
892 imageData_.y = static_cast<int32_t>(dy * density);
893 imageData_.dirtyWidth = imageData_.dirtyX < 0 ? std::min(imageData_.dirtyX + imageData_.dirtyWidth, imgWidth)
894 : std::min(imgWidth - imageData_.dirtyX, imageData_.dirtyWidth);
895 imageData_.dirtyHeight = imageData_.dirtyY < 0 ? std::min(imageData_.dirtyY + imageData_.dirtyHeight, imgHeight)
896 : std::min(imgHeight - imageData_.dirtyY, imageData_.dirtyHeight);
897 auto buffer = imageData->data;
898 int32_t bufferLength = static_cast<int32_t>(buffer.size());
899 imageData_.data = std::vector<uint32_t>();
900 for (int32_t i = std::max(imageData_.dirtyY, 0); i < imageData_.dirtyY + imageData_.dirtyHeight; ++i) {
901 for (int32_t j = std::max(imageData_.dirtyX, 0); j < imageData_.dirtyX + imageData_.dirtyWidth; ++j) {
902 uint32_t idx = static_cast<uint32_t>(4 * (j + imgWidth * i));
903 if (bufferLength > static_cast<int32_t>(idx + ALPHA_INDEX)) {
904 uint8_t alpha = buffer[idx + 3]; // idx + 3: The 4th byte format: alpha
905 uint8_t red = buffer[idx]; // idx: the 1st byte format: red
906 uint8_t green = buffer[idx + 1]; // idx + 1: The 2nd byte format: green
907 uint8_t blue = buffer[idx + 2]; // idx + 2: The 3rd byte format: blue
908 imageData_.data.emplace_back(Color::FromARGB(alpha, red, green, blue).GetValue());
909 }
910 }
911 }
912 renderingContext2DModel_->PutImageData(imageData_);
913 }
914 } // namespace OHOS::Ace::Framework
915