• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     double width = textMetrics.width / density;
312     double height = textMetrics.height / density;
313     double actualBoundingBoxLeft = textMetrics.actualBoundingBoxLeft / density;
314     double actualBoundingBoxRight = textMetrics.actualBoundingBoxRight / density;
315     double actualBoundingBoxAscent = textMetrics.actualBoundingBoxAscent / density;
316     double actualBoundingBoxDescent = textMetrics.actualBoundingBoxDescent / density;
317     double alphabeticBaseline = textMetrics.alphabeticBaseline / density;
318     double emHeightAscent = textMetrics.emHeightAscent / density;
319     double emHeightDescent = textMetrics.emHeightDescent / density;
320     double fontBoundingBoxAscent = textMetrics.fontBoundingBoxAscent / density;
321     double fontBoundingBoxDescent = textMetrics.fontBoundingBoxDescent / density;
322     double hangingBaseline = textMetrics.hangingBaseline / density;
323     double ideographicBaseline = textMetrics.ideographicBaseline / density;
324 
325     Metrics metrics = { width, height, actualBoundingBoxLeft, actualBoundingBoxRight, actualBoundingBoxAscent,
326         actualBoundingBoxDescent, alphabeticBaseline, emHeightAscent, emHeightDescent, fontBoundingBoxAscent,
327         fontBoundingBoxDescent, hangingBaseline, ideographicBaseline };
328     return metrics;
329 }
330 
Stroke()331 void NativeCanvasRenderer::Stroke()
332 {
333     auto fillRule = CanvasFillRule::NONZERO;
334     renderingContext2DModel_->SetStrokeRuleForPath(fillRule);
335 }
336 
Stroke(const sptr<NativeCanvasPath> & canvasPath)337 void NativeCanvasRenderer::Stroke(const sptr<NativeCanvasPath>& canvasPath)
338 {
339     auto path = canvasPath->GetCanvasPath2d();
340     auto fillRule = CanvasFillRule::NONZERO;
341 
342     renderingContext2DModel_->SetStrokeRuleForPath2D(fillRule, path);
343 }
344 
BeginPath()345 void NativeCanvasRenderer::BeginPath()
346 {
347     renderingContext2DModel_->BeginPath();
348 }
349 
MoveTo(const double x,const double y)350 void NativeCanvasRenderer::MoveTo(const double x, const double y)
351 {
352     double density = GetDensity();
353     renderingContext2DModel_->MoveTo(x * density, y * density);
354 }
355 
LineTo(const double x,const double y)356 void NativeCanvasRenderer::LineTo(const double x, const double y)
357 {
358     double density = GetDensity();
359     renderingContext2DModel_->LineTo(x * density, y * density);
360 }
361 
ClosePath()362 void NativeCanvasRenderer::ClosePath()
363 {
364     renderingContext2DModel_->ClosePath();
365 }
366 
BezierCurveTo(const BezierCurveParam & param)367 void NativeCanvasRenderer::BezierCurveTo(const BezierCurveParam& param)
368 {
369     double density = GetDensity();
370     BezierCurveParam beParam;
371     beParam.cp1x = param.cp1x * density;
372     beParam.cp1y = param.cp1y * density;
373     beParam.cp2x = param.cp2x * density;
374     beParam.cp2y = param.cp2y * density;
375     beParam.x = param.x * density;
376     beParam.y = param.y * density;
377     renderingContext2DModel_->BezierCurveTo(beParam);
378 }
379 
QuadraticCurveTo(const QuadraticCurveParam & param)380 void NativeCanvasRenderer::QuadraticCurveTo(const QuadraticCurveParam& param)
381 {
382     double density = GetDensity();
383     QuadraticCurveParam quParam;
384     quParam.cpx = param.cpx * density;
385     quParam.cpy = param.cpy * density;
386     quParam.x = param.x * density;
387     quParam.y = param.y * density;
388     renderingContext2DModel_->QuadraticCurveTo(quParam);
389 }
390 
Arc(const ArcParam & param)391 void NativeCanvasRenderer::Arc(const ArcParam& param)
392 {
393     ArcParam arcParam = param;
394     double density = GetDensity();
395     arcParam.x = param.x * density;
396     arcParam.y = param.y * density;
397     arcParam.radius = param.radius * density;
398     renderingContext2DModel_->Arc(arcParam);
399 }
400 
ArcTo(const ArcToParam & param)401 void NativeCanvasRenderer::ArcTo(const ArcToParam& param)
402 {
403     ArcToParam arcToParam;
404     double density = GetDensity();
405     arcToParam.x1 = param.x1 * density;
406     arcToParam.y1 = param.y1 * density;
407     arcToParam.x2 = param.x2 * density;
408     arcToParam.y2 = param.y2 * density;
409     arcToParam.radius = param.radius * density;
410     renderingContext2DModel_->ArcTo(arcToParam);
411 }
412 
Ellipse(const EllipseParam & param)413 void NativeCanvasRenderer::Ellipse(const EllipseParam& param)
414 {
415     EllipseParam elParam = param;
416     double density = GetDensity();
417     elParam.x = param.x * density;
418     elParam.y = param.y * density;
419     elParam.radiusX = param.radiusX * density;
420     elParam.radiusY = param.radiusY * density;
421     renderingContext2DModel_->Ellipse(elParam);
422 }
423 
SaveLayer()424 void NativeCanvasRenderer::SaveLayer()
425 {
426     renderingContext2DModel_->SaveLayer();
427 }
428 
SetFilter(const std::string & value)429 void NativeCanvasRenderer::SetFilter(const std::string& value)
430 {
431     renderingContext2DModel_->SetFilterParam(value);
432 }
433 
GetHeight()434 double NativeCanvasRenderer::GetHeight()
435 {
436     double width = 0.0;
437     auto canvasRenderingContext2DModel = AceType::DynamicCast<CanvasRenderingContext2DModel>(renderingContext2DModel_);
438     canvasRenderingContext2DModel->GetWidth(width);
439     return width;
440 }
441 
NormalRect(const Rect & rect)442 void NativeCanvasRenderer::NormalRect(const Rect& rect)
443 {
444     renderingContext2DModel_->AddRect(rect * GetDensity());
445 }
446 
Fill()447 void NativeCanvasRenderer::Fill()
448 {
449     auto fillRule = CanvasFillRule::NONZERO;
450 
451     renderingContext2DModel_->SetFillRuleForPath(fillRule);
452 }
453 
Fill(const std::string & ruleStr)454 void NativeCanvasRenderer::Fill(const std::string& ruleStr)
455 {
456     auto fillRule = ruleStr == "evenodd" ? CanvasFillRule::EVENODD : CanvasFillRule::NONZERO;
457     renderingContext2DModel_->SetFillRuleForPath(fillRule);
458     return;
459 }
460 
Fill(const sptr<NativeCanvasPath> & canvasPath,const std::string & ruleStr)461 void NativeCanvasRenderer::Fill(const sptr<NativeCanvasPath>& canvasPath, const std::string& ruleStr)
462 {
463     auto fillRule = ruleStr == "evenodd" ? CanvasFillRule::EVENODD : CanvasFillRule::NONZERO;
464     auto path = canvasPath->GetCanvasPath2d();
465     renderingContext2DModel_->SetFillRuleForPath2D(fillRule, path);
466 }
467 
Clip()468 void NativeCanvasRenderer::Clip()
469 {
470     auto fillRule = CanvasFillRule::NONZERO;
471     renderingContext2DModel_->SetClipRuleForPath(fillRule);
472 }
473 
Clip(const std::string & ruleStr)474 void NativeCanvasRenderer::Clip(const std::string& ruleStr)
475 {
476     auto fillRule = ruleStr == "evenodd" ? CanvasFillRule::EVENODD : CanvasFillRule::NONZERO;
477     renderingContext2DModel_->SetClipRuleForPath(fillRule);
478     return;
479 }
480 
Clip(const sptr<NativeCanvasPath> & canvasPath,const std::string & ruleStr)481 void NativeCanvasRenderer::Clip(const sptr<NativeCanvasPath>& canvasPath, const std::string& ruleStr)
482 {
483     auto fillRule = ruleStr == "evenodd" ? CanvasFillRule::EVENODD : CanvasFillRule::NONZERO;
484     auto path = canvasPath->GetCanvasPath2d();
485     renderingContext2DModel_->SetClipRuleForPath2D(fillRule, path);
486 }
487 
Rotate(const double angle)488 void NativeCanvasRenderer::Rotate(const double angle)
489 {
490     renderingContext2DModel_->CanvasRendererRotate(angle);
491 }
492 
Scale(const double x,const double y)493 void NativeCanvasRenderer::Scale(const double x, const double y)
494 {
495     renderingContext2DModel_->CanvasRendererScale(x, y);
496 }
497 
Transform(const TransformParam & param)498 void NativeCanvasRenderer::Transform(const TransformParam& param)
499 {
500     renderingContext2DModel_->Transform(param);
501 }
502 
SetTransform(TransformParam param)503 void NativeCanvasRenderer::SetTransform(TransformParam param)
504 {
505     double density = GetDensity();
506     param.translateX *= density;
507     param.translateY *= density;
508     renderingContext2DModel_->SetTransform(param, true);
509 }
510 
SetTransform(unsigned int id,const TransformParam & transform)511 void NativeCanvasRenderer::SetTransform(unsigned int id, const TransformParam& transform)
512 {
513     if (id >= 0 && id <= patternCount_) {
514         renderingContext2DModel_->SetTransform(pattern_[id], transform);
515     }
516 }
517 
SetTransformByMatrix(const sptr<NativeMatrix2d> & matrix2d)518 void NativeCanvasRenderer::SetTransformByMatrix(const sptr<NativeMatrix2d>& matrix2d)
519 {
520     TransformParam param = matrix2d->GetTransform();
521     renderingContext2DModel_->SetTransform(param, false);
522 }
523 
ResetTransform()524 void NativeCanvasRenderer::ResetTransform()
525 {
526     renderingContext2DModel_->ResetTransform();
527 }
528 
Translate(const double x,const double y)529 void NativeCanvasRenderer::Translate(const double x, const double y)
530 {
531     double density = GetDensity();
532     renderingContext2DModel_->Translate(x * density, y * density);
533 }
534 
Restore()535 void NativeCanvasRenderer::Restore()
536 {
537     if (!savePaintState_.empty()) {
538         paintState_ = savePaintState_.back();
539         savePaintState_.pop_back();
540     }
541     renderingContext2DModel_->Restore();
542 }
543 
Save()544 void NativeCanvasRenderer::Save()
545 {
546     savePaintState_.push_back(paintState_);
547     renderingContext2DModel_->CanvasRendererSave();
548 }
549 
CreateLinearGradient(const double x0,const double y0,const double x1,const double y1)550 int64_t NativeCanvasRenderer::CreateLinearGradient(const double x0, const double y0, const double x1, const double y1)
551 {
552     double density = GetDensity();
553     Offset beginOffset = Offset(x0 * density, y0 * density);
554     Offset endOffset = Offset(x1 * density, y1 * density);
555 
556     Gradient gradient = Gradient();
557     gradient.SetType(GradientType::LINEAR);
558     gradient.SetBeginOffset(beginOffset);
559     gradient.SetEndOffset(endOffset);
560 
561     auto nativeCanvasGradient = FFIData::Create<NativeCanvasGradient>(gradient);
562     if (nativeCanvasGradient == nullptr) {
563         return FFI_ERROR_CODE;
564     }
565     return nativeCanvasGradient->GetID();
566 }
567 
CreateRadialGradient(const double x0,const double y0,const double r0,const double x1,const double y1,const double r1)568 int64_t NativeCanvasRenderer::CreateRadialGradient(
569     const double x0, const double y0, const double r0, const double x1, const double y1, const double r1)
570 {
571     double density = GetDensity();
572     Offset innerCenter = Offset(x0 * density, y0 * density);
573     Offset outerCenter = Offset(x1 * density, y1 * density);
574 
575     Gradient gradient = Gradient();
576     gradient.SetType(GradientType::RADIAL);
577     gradient.SetBeginOffset(innerCenter);
578     gradient.SetEndOffset(outerCenter);
579     gradient.SetInnerRadius(r0 * density);
580     gradient.SetOuterRadius(r1 * density);
581 
582     auto nativeCanvasGradient = FFIData::Create<NativeCanvasGradient>(gradient);
583     if (nativeCanvasGradient == nullptr) {
584         return FFI_ERROR_CODE;
585     }
586     return nativeCanvasGradient->GetID();
587 }
588 
CreateConicGradient(const double startAngle,const double x,const double y)589 int64_t NativeCanvasRenderer::CreateConicGradient(const double startAngle, const double x, const double y)
590 {
591     double density = GetDensity();
592     Gradient gradient = Gradient();
593     gradient.SetType(GradientType::CONIC);
594     gradient.GetConicGradient().startAngle = AnimatableDimension(Dimension(fmod(startAngle, (EVEN_CHECK * M_PI))));
595     gradient.GetConicGradient().centerX = AnimatableDimension(Dimension(x * density));
596     gradient.GetConicGradient().centerY = AnimatableDimension(Dimension(y * density));
597 
598     auto nativeCanvasGradient = FFIData::Create<NativeCanvasGradient>(gradient);
599     if (nativeCanvasGradient == nullptr) {
600         return FFI_ERROR_CODE;
601     }
602     return nativeCanvasGradient->GetID();
603 }
604 
DrawImage(const CanvasImage & image)605 void NativeCanvasRenderer::DrawImage(const CanvasImage& image)
606 {
607     ImageInfo imageInfo;
608     imageInfo.image = image;
609     imageInfo.isImage = true;
610     renderingContext2DModel_->DrawImage(imageInfo);
611 }
612 
DrawImage(const RefPtr<OHOS::Ace::PixelMap> & pixelMap,const CanvasImage & image)613 void NativeCanvasRenderer::DrawImage(const RefPtr<OHOS::Ace::PixelMap>& pixelMap, const CanvasImage& image)
614 {
615     ImageInfo imageInfo;
616     imageInfo.image = image;
617     imageInfo.isImage = false;
618     imageInfo.pixelMap = pixelMap;
619     renderingContext2DModel_->DrawPixelMap(imageInfo);
620 }
621 
GetImageData(const double left,const double top,const double width,const double height)622 std::unique_ptr<ImageData> NativeCanvasRenderer::GetImageData(
623     const double left, const double top, const double width, const double height)
624 {
625     std::unique_ptr<ImageData> canvasData;
626     ImageSize imageSize;
627     imageSize.left = left;
628     imageSize.top = top;
629     imageSize.width = width;
630     imageSize.height = height;
631     canvasData = renderingContext2DModel_->GetImageData(imageSize);
632     return canvasData;
633 }
634 
GetNativeImageData(const double left,const double top,const double width,const double height)635 int64_t NativeCanvasRenderer::GetNativeImageData(
636     const double left, const double top, const double width, const double height)
637 {
638     ImageSize imageSize;
639     double density = GetDensity();
640     imageSize.left = left * density;
641     imageSize.top = top * density;
642     imageSize.width = width * density + DIFF;
643     imageSize.height = height * density + DIFF;
644 
645     uint32_t finalWidth = static_cast<uint32_t>(std::abs(imageSize.width));
646     uint32_t finalHeight = static_cast<uint32_t>(std::abs(imageSize.height));
647     int32_t length = static_cast<int32_t>(finalHeight * finalWidth * 4);
648     std::vector<uint8_t> buffer(length, 0xff);
649     auto imagdata = FFI::FFIData::Create<NativeImageData>();
650     if (finalHeight > 0 && finalWidth > (UINT32_MAX / finalHeight)) {
651         imagdata->height_ = 0;
652         imagdata->width_ = 0;
653         imagdata->data = buffer;
654         return imagdata->GetID();
655     }
656     renderingContext2DModel_->GetImageDataModel(imageSize, buffer.data());
657     imagdata->height_ = static_cast<int32_t>(finalHeight);
658     imagdata->width_ = static_cast<int32_t>(finalWidth);
659     imagdata->data = buffer;
660     return imagdata->GetID();
661 }
662 
GetPixelMap(double left,double top,double width,double height)663 int64_t NativeCanvasRenderer::GetPixelMap(double left, double top, double width, double height)
664 {
665     auto finalHeight = static_cast<uint32_t>(std::abs(height));
666     auto finalWidth = static_cast<uint32_t>(std::abs(width));
667     if (finalHeight > 0 && finalWidth > (UINT32_MAX / finalHeight)) {
668         return 0;
669     }
670     double density = GetDensity();
671     ImageSize imageSize;
672     imageSize.left = left * density;
673     imageSize.top = top * density;
674     imageSize.width = finalWidth * density + DIFF;
675     imageSize.height = finalHeight * density + DIFF;
676     finalHeight = static_cast<uint32_t>(std::abs(imageSize.height));
677     finalHeight = static_cast<uint32_t>(std::abs(imageSize.width));
678     if (height > 0 && width > (UINT32_MAX / height)) {
679         LOGE("NativeCanvasRenderer GetPixelMap failed");
680         return 0;
681     }
682     auto pixelmap = renderingContext2DModel_->GetPixelMap(imageSize);
683     if (pixelmap) {
684         auto ret = FFIData::Create<OHOS::Media::PixelMapImpl>(pixelmap->GetPixelMapSharedPtr());
685         if (ret == nullptr) {
686             return FFI_ERROR_CODE;
687         }
688         return ret->GetID();
689     } else {
690         LOGE("NativeCanvasRenderer GetPixelMap failed");
691         return 0;
692     }
693 }
694 
SetDirection(const std::string & directionStr)695 void NativeCanvasRenderer::SetDirection(const std::string& directionStr)
696 {
697     auto direction = ConvertStrToTextDirection(directionStr);
698     renderingContext2DModel_->SetTextDirection(direction);
699 }
700 
GetJsonData(const std::string & path)701 std::string NativeCanvasRenderer::GetJsonData(const std::string& path)
702 {
703     std::string jsonData = renderingContext2DModel_->GetJsonData(path);
704     return jsonData;
705 }
706 
RestoreLayer()707 void NativeCanvasRenderer::RestoreLayer()
708 {
709     renderingContext2DModel_->RestoreLayer();
710 }
711 
Reset()712 void NativeCanvasRenderer::Reset()
713 {
714     paintState_ = PaintState();
715     std::vector<PaintState>().swap(savePaintState_);
716     isInitializeShadow_ = false;
717     renderingContext2DModel_->Reset();
718 }
719 
CreatePattern(int64_t bitMapId,const std::string & repeat)720 int64_t NativeCanvasRenderer::CreatePattern(int64_t bitMapId, const std::string& repeat)
721 {
722     auto renderImage = FFIData::GetData<CJRenderImage>(bitMapId);
723     if (renderImage == nullptr) {
724         LOGE("canvas createCanvasPattern error, Cannot get CJRenderImage by id: %{public}" PRId64, bitMapId);
725         return 0;
726     }
727     auto pattern = std::make_shared<Pattern>();
728     pattern->SetImgSrc(renderImage->GetSrc());
729     pattern->SetImageWidth(renderImage->GetWidth());
730     pattern->SetImageHeight(renderImage->GetHeight());
731     pattern->SetRepetition(repeat);
732 #if !defined(PREVIEW)
733     auto pixelMap = renderImage->GetPixelMap();
734     pattern->SetPixelMap(pixelMap);
735 #endif
736 
737     pattern_[patternCount_] = pattern;
738     auto nativeCanvasPattern = FFIData::Create<NativeCanvasPattern>();
739     if (nativeCanvasPattern == nullptr) {
740         return FFI_ERROR_CODE;
741     }
742     nativeCanvasPattern->SetCanvasRenderer(this);
743     nativeCanvasPattern->SetId(patternCount_);
744     nativeCanvasPattern->SetUnit(GetUnit());
745     patternCount_++;
746     return nativeCanvasPattern->GetID();
747 }
748 
GetPatternPtr(int32_t id)749 std::shared_ptr<Pattern> NativeCanvasRenderer::GetPatternPtr(int32_t id)
750 {
751     if (id < 0 || id >= static_cast<int32_t>(pattern_.size())) {
752         return std::shared_ptr<Pattern>();
753     }
754     return pattern_[id];
755 }
756 
GetTransform()757 int64_t NativeCanvasRenderer::GetTransform()
758 {
759     TransformParam param = renderingContext2DModel_->GetTransform();
760     auto nativeMatrix2d = FFIData::Create<NativeMatrix2d>();
761     nativeMatrix2d->SetTransform(param);
762     return nativeMatrix2d->GetID();
763 }
764 
SetPixelMap(const RefPtr<OHOS::Ace::PixelMap> & pixelMap)765 void NativeCanvasRenderer::SetPixelMap(const RefPtr<OHOS::Ace::PixelMap>& pixelMap)
766 {
767 #if !defined(PREVIEW)
768     ImageInfo imageInfo;
769     imageInfo.pixelMap = pixelMap;
770     renderingContext2DModel_->DrawPixelMap(imageInfo);
771 #endif
772 }
773 
SetDensity()774 void NativeCanvasRenderer::SetDensity()
775 {
776     double density = GetDensity(true);
777     renderingContext2DModel_->SetDensity(density);
778 }
779 
ToDataUrl(const std::string type,const double quality)780 std::string NativeCanvasRenderer::ToDataUrl(const std::string type, const double quality)
781 {
782     std::string result = renderingContext2DModel_->ToDataURL(type, quality);
783     return result;
784 }
785 
GetWidth()786 double NativeCanvasRenderer::GetWidth()
787 {
788     double width = 0.0;
789     auto canvasRenderingContext2DModel = AceType::DynamicCast<CanvasRenderingContext2DModel>(renderingContext2DModel_);
790     CHECK_NULL_RETURN(canvasRenderingContext2DModel, -1);
791     canvasRenderingContext2DModel->GetWidth(width);
792     double density = !NearZero(GetDensity()) ? GetDensity() : 1.0;
793     width /= density;
794     return width;
795 }
796 
TransferFromImageBitmap(const sptr<CJRenderImage> cjImage)797 void NativeCanvasRenderer::TransferFromImageBitmap(const sptr<CJRenderImage> cjImage)
798 {
799     auto canvasRenderingContext2DModel = AceType::DynamicCast<CanvasRenderingContext2DModel>(renderingContext2DModel_);
800     CHECK_NULL_VOID(canvasRenderingContext2DModel);
801 #ifdef PIXEL_MAP_SUPPORTED
802     canvasRenderingContext2DModel->TransferFromImageBitmap(cjImage->GetPixelMap());
803 #else
804     auto imageData = cjImage->imageData;
805     CHECK_NULL_VOID(imageData);
806     canvasRenderingContext2DModel->TransferFromImageBitmap(imageData);
807 #endif
808 }
809 
CreateImageData(const double height,const double width)810 int64_t NativeCanvasRenderer::CreateImageData(const double height, const double width)
811 {
812     auto imageData = FFIData::Create<NativeImageData>();
813     double density = GetDensity();
814     int32_t finalWidth = static_cast<int32_t>(std::abs(width * density + DIFF));
815     int32_t finalHeight = static_cast<int32_t>(std::abs(height * density + DIFF));
816     int32_t result = finalWidth * finalHeight * PIXEL_SIZE;
817     std::vector<uint8_t> bufferArray;
818     for (int32_t i = 0; i < result; i++) {
819         bufferArray.emplace_back(0xff);
820     }
821     imageData->height_ = finalHeight;
822     imageData->width_ = finalHeight;
823     imageData->data = bufferArray;
824     return imageData->GetID();
825 }
826 
CreateImageData(const sptr<NativeImageData> imageData)827 int64_t NativeCanvasRenderer::CreateImageData(const sptr<NativeImageData> imageData)
828 {
829     auto ret = FFIData::Create<NativeImageData>();
830     double density = GetDensity();
831     int32_t finalWidth = static_cast<int32_t>(std::abs(imageData->width_ * density + DIFF));
832     int32_t finalHeight = static_cast<int32_t>(std::abs(imageData->height_ * density + DIFF));
833     int32_t result = finalWidth * finalHeight * PIXEL_SIZE;
834     std::vector<uint8_t> bufferArray;
835     for (int32_t i = 0; i < result; i++) {
836         bufferArray.emplace_back(0xff);
837     }
838     ret->height_ = finalHeight;
839     ret->width_ = finalHeight;
840     ret->data = bufferArray;
841     return ret->GetID();
842 }
843 
PutImageData(const sptr<NativeImageData> imageData,const double dx,const double dy,const double dirtyX,const double dirtyY,const double dirtyWidth,const double dirtyHeight)844 void NativeCanvasRenderer::PutImageData(const sptr<NativeImageData> imageData, const double dx, const double dy,
845     const double dirtyX, const double dirtyY, const double dirtyWidth, const double dirtyHeight)
846 {
847     double density = GetDensity();
848     int32_t imgWidth = imageData->GetWidth();
849     int32_t imgHeight = imageData->GetHeight();
850     ImageData imageData_ = { .dirtyWidth = imgWidth, .dirtyHeight = imgHeight };
851     imageData_.x = static_cast<int32_t>(dx * density);
852     imageData_.y = static_cast<int32_t>(dy * density);
853     imageData_.dirtyX = static_cast<int32_t>(dirtyX * density);
854     imageData_.dirtyY = static_cast<int32_t>(dirtyY * density);
855     imageData_.dirtyHeight = static_cast<int32_t>(dirtyHeight * density);
856     imageData_.dirtyWidth = static_cast<int32_t>(dirtyWidth * density);
857     imageData_.dirtyWidth = imageData_.dirtyX < 0 ? std::min(imageData_.dirtyX + imageData_.dirtyWidth, imgWidth)
858                                                   : std::min(imgWidth - imageData_.dirtyX, imageData_.dirtyWidth);
859     imageData_.dirtyHeight = imageData_.dirtyY < 0 ? std::min(imageData_.dirtyY + imageData_.dirtyHeight, imgHeight)
860                                                    : std::min(imgHeight - imageData_.dirtyY, imageData_.dirtyHeight);
861     auto buffer = imageData->data;
862     int32_t bufferLength = static_cast<int32_t>(buffer.size());
863     imageData_.data = std::vector<uint32_t>();
864     for (int32_t i = std::max(imageData_.dirtyY, 0); i < imageData_.dirtyY + imageData_.dirtyHeight; ++i) {
865         for (int32_t j = std::max(imageData_.dirtyX, 0); j < imageData_.dirtyX + imageData_.dirtyWidth; ++j) {
866             uint32_t idx = static_cast<uint32_t>(4 * (j + imgWidth * i));
867             if (bufferLength > static_cast<int32_t>(idx + ALPHA_INDEX)) {
868                 uint8_t alpha = buffer[idx + 3]; // idx + 3: The 4th byte format: alpha
869                 uint8_t red = buffer[idx];       // idx: the 1st byte format: red
870                 uint8_t green = buffer[idx + 1]; // idx + 1: The 2nd byte format: green
871                 uint8_t blue = buffer[idx + 2];  // idx + 2: The 3rd byte format: blue
872                 imageData_.data.emplace_back(Color::FromARGB(alpha, red, green, blue).GetValue());
873             }
874         }
875     }
876     renderingContext2DModel_->PutImageData(imageData_);
877 }
878 
PutImageData(const sptr<NativeImageData> imageData,const double dx,const double dy)879 void NativeCanvasRenderer::PutImageData(const sptr<NativeImageData> imageData, const double dx, const double dy)
880 {
881     double density = GetDensity();
882     int32_t imgWidth = imageData->GetWidth();
883     int32_t imgHeight = imageData->GetHeight();
884     ImageData imageData_ = { .dirtyWidth = imgWidth, .dirtyHeight = imgHeight };
885     imageData_.x = static_cast<int32_t>(dx * density);
886     imageData_.y = static_cast<int32_t>(dy * density);
887     imageData_.dirtyWidth = imageData_.dirtyX < 0 ? std::min(imageData_.dirtyX + imageData_.dirtyWidth, imgWidth)
888                                                   : std::min(imgWidth - imageData_.dirtyX, imageData_.dirtyWidth);
889     imageData_.dirtyHeight = imageData_.dirtyY < 0 ? std::min(imageData_.dirtyY + imageData_.dirtyHeight, imgHeight)
890                                                    : std::min(imgHeight - imageData_.dirtyY, imageData_.dirtyHeight);
891     auto buffer = imageData->data;
892     int32_t bufferLength = static_cast<int32_t>(buffer.size());
893     imageData_.data = std::vector<uint32_t>();
894     for (int32_t i = std::max(imageData_.dirtyY, 0); i < imageData_.dirtyY + imageData_.dirtyHeight; ++i) {
895         for (int32_t j = std::max(imageData_.dirtyX, 0); j < imageData_.dirtyX + imageData_.dirtyWidth; ++j) {
896             uint32_t idx = static_cast<uint32_t>(4 * (j + imgWidth * i));
897             if (bufferLength > static_cast<int32_t>(idx + ALPHA_INDEX)) {
898                 uint8_t alpha = buffer[idx + 3]; // idx + 3: The 4th byte format: alpha
899                 uint8_t red = buffer[idx];       // idx: the 1st byte format: red
900                 uint8_t green = buffer[idx + 1]; // idx + 1: The 2nd byte format: green
901                 uint8_t blue = buffer[idx + 2];  // idx + 2: The 3rd byte format: blue
902                 imageData_.data.emplace_back(Color::FromARGB(alpha, red, green, blue).GetValue());
903             }
904         }
905     }
906     renderingContext2DModel_->PutImageData(imageData_);
907 }
908 } // namespace OHOS::Ace::Framework
909