• 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     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