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