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 <cinttypes>
19 #include <memory>
20 
21 #include "base/log/log_wrapper.h"
22 #include "core/common/container.h"
23 
24 using namespace OHOS;
25 
26 namespace OHOS::Ace::Framework {
27 
28 namespace {
29 const int EVEN_CHECK = 2;
30 } // namespace
31 
NativeCanvasRenderer(bool antialias)32 NativeCanvasRenderer::NativeCanvasRenderer(bool antialias) : FFIData()
33 {
34     renderingContext2DModel_ = AceType::MakeRefPtr<NG::CanvasRenderingContext2DModelNG>();
35     antialias_ = antialias;
36 }
37 
~NativeCanvasRenderer()38 NativeCanvasRenderer::~NativeCanvasRenderer()
39 {
40     LOGI("Native CanvasRenderer Destroyed: %{public}" PRId64, GetID());
41 }
42 
SetCanvasPattern(const RefPtr<AceType> & canvas)43 void NativeCanvasRenderer::SetCanvasPattern(const RefPtr<AceType>& canvas)
44 {
45     canvasPattern_ = canvas;
46     renderingContext2DModel_->SetPattern(canvas);
47     if (isInitializeShadow_) {
48         return;
49     }
50     isInitializeShadow_ = true;
51     renderingContext2DModel_->SetShadowColor(Color::TRANSPARENT);
52 }
53 
SetAntiAlias()54 void NativeCanvasRenderer::SetAntiAlias()
55 {
56     renderingContext2DModel_->SetAntiAlias(antialias_);
57 }
58 
MakePath2D(const std::string & capStr)59 RefPtr<CanvasPath2D> NativeCanvasRenderer::MakePath2D(const std::string& capStr)
60 {
61     return AceType::MakeRefPtr<CanvasPath2D>(capStr);
62 }
63 
SetFillStyle(const Color & color)64 void NativeCanvasRenderer::SetFillStyle(const Color& color)
65 {
66     renderingContext2DModel_->SetFillColor(color, true);
67 }
68 
SetFillStyle(const sptr<NativeCanvasGradient> & nativeCanvasGradient)69 void NativeCanvasRenderer::SetFillStyle(const sptr<NativeCanvasGradient>& nativeCanvasGradient)
70 {
71     auto gradient = std::make_shared<Gradient>(nativeCanvasGradient->GetGradient());
72     renderingContext2DModel_->SetFillGradient(gradient);
73 }
74 
SetLineWidth(const double lineWidth)75 void NativeCanvasRenderer::SetLineWidth(const double lineWidth)
76 {
77     renderingContext2DModel_->SetLineWidth(lineWidth);
78 }
79 
SetStrokeStyle(const Color & color)80 void NativeCanvasRenderer::SetStrokeStyle(const Color& color)
81 {
82     renderingContext2DModel_->SetStrokeColor(color, true);
83 }
84 
SetStrokeStyle(const sptr<NativeCanvasGradient> & nativeCanvasGradient)85 void NativeCanvasRenderer::SetStrokeStyle(const sptr<NativeCanvasGradient>& nativeCanvasGradient)
86 {
87     auto gradient = std::make_shared<Gradient>(nativeCanvasGradient->GetGradient());
88     renderingContext2DModel_->SetStrokeGradient(gradient);
89 }
90 
SetLineCap(const LineCapStyle lineCap)91 void NativeCanvasRenderer::SetLineCap(const LineCapStyle lineCap)
92 {
93     renderingContext2DModel_->SetLineCap(lineCap);
94 }
95 
SetLineJoin(const LineJoinStyle lineJoin)96 void NativeCanvasRenderer::SetLineJoin(const LineJoinStyle lineJoin)
97 {
98     renderingContext2DModel_->SetLineJoin(lineJoin);
99 }
100 
SetMiterLimit(double limit)101 void NativeCanvasRenderer::SetMiterLimit(double limit)
102 {
103     renderingContext2DModel_->SetMiterLimit(limit);
104 }
105 
SetFont(const FontStyle fontStyle,const std::string & fontWeight,const Dimension & fontSize,const std::string & fontFamily)106 void NativeCanvasRenderer::SetFont(
107     const FontStyle fontStyle, const std::string& fontWeight, const Dimension& fontSize, const std::string& fontFamily)
108 {
109     auto weight = ConvertStrToFontWeight(fontWeight);
110     auto families = ConvertStrToFontFamilies(fontFamily);
111 
112     renderingContext2DModel_->SetFontStyle(fontStyle);
113     renderingContext2DModel_->SetFontWeight(weight);
114     renderingContext2DModel_->SetFontSize(fontSize);
115     renderingContext2DModel_->SetFontFamilies(families);
116 
117     style_.SetFontStyle(fontStyle);
118     style_.SetFontWeight(weight);
119     style_.SetFontSize(fontSize);
120     style_.SetFontFamilies(families);
121 }
122 
SetTextAlign(const TextAlign align)123 void NativeCanvasRenderer::SetTextAlign(const TextAlign align)
124 {
125     renderingContext2DModel_->SetTextAlign(align);
126     paintState_.SetTextAlign(align);
127 }
128 
SetTextBaseline(const TextBaseline baseline)129 void NativeCanvasRenderer::SetTextBaseline(const TextBaseline baseline)
130 {
131     renderingContext2DModel_->SetTextBaseline(baseline);
132     style_.SetTextBaseline(baseline);
133 }
134 
SetGlobalAlpha(double alpha)135 void NativeCanvasRenderer::SetGlobalAlpha(double alpha)
136 {
137     renderingContext2DModel_->SetGlobalAlpha(alpha);
138 }
139 
SetLineDash(std::vector<double> & lineDash)140 void NativeCanvasRenderer::SetLineDash(std::vector<double>& lineDash)
141 {
142     if (lineDash.size() % EVEN_CHECK != 0) {
143         lineDash.insert(lineDash.end(), lineDash.begin(), lineDash.end());
144     }
145 
146     renderingContext2DModel_->SetLineDash(lineDash);
147 }
148 
SetLineDashOffset(const double lineDashOffset)149 void NativeCanvasRenderer::SetLineDashOffset(const double lineDashOffset)
150 {
151     renderingContext2DModel_->SetLineDashOffset(lineDashOffset);
152 }
153 
SetGlobalCompositeOperation(const CompositeOperation type)154 void NativeCanvasRenderer::SetGlobalCompositeOperation(const CompositeOperation type)
155 {
156     renderingContext2DModel_->SetCompositeType(type);
157 }
158 
SetShadowBlur(const double blur)159 void NativeCanvasRenderer::SetShadowBlur(const double blur)
160 {
161     renderingContext2DModel_->SetShadowBlur(blur);
162 }
163 
SetShadowColor(const Color & color)164 void NativeCanvasRenderer::SetShadowColor(const Color& color)
165 {
166     renderingContext2DModel_->SetShadowColor(color);
167 }
168 
SetShadowOffsetX(const double offsetX)169 void NativeCanvasRenderer::SetShadowOffsetX(const double offsetX)
170 {
171     renderingContext2DModel_->SetShadowOffsetX(offsetX);
172 }
173 
SetShadowOffsetY(const double offsetY)174 void NativeCanvasRenderer::SetShadowOffsetY(const double offsetY)
175 {
176     renderingContext2DModel_->SetShadowOffsetX(offsetY);
177 }
178 
SetImageSmoothingEnabled(const bool enabled)179 void NativeCanvasRenderer::SetImageSmoothingEnabled(const bool enabled)
180 {
181     renderingContext2DModel_->SetSmoothingEnabled(enabled);
182 }
183 
SetImageSmoothingQuality(const std::string & quality)184 void NativeCanvasRenderer::SetImageSmoothingQuality(const std::string& quality)
185 {
186     LOGE("canvas error: imageSmoothingQuality is not support in new pipeline");
187 }
188 
FillRect(const Rect & rect)189 void NativeCanvasRenderer::FillRect(const Rect& rect)
190 {
191     renderingContext2DModel_->FillRect(rect);
192 }
193 
StrokeRect(const Rect & rect)194 void NativeCanvasRenderer::StrokeRect(const Rect& rect)
195 {
196     renderingContext2DModel_->StrokeRect(rect);
197 }
198 
ClearRect(const Rect & rect)199 void NativeCanvasRenderer::ClearRect(const Rect& rect)
200 {
201     renderingContext2DModel_->ClearRect(rect);
202 }
203 
FillText(const double x,const double y,const std::string & text)204 void NativeCanvasRenderer::FillText(const double x, const double y, const std::string& text)
205 {
206     FillTextInfo textInfo;
207     textInfo.text = text;
208     textInfo.x = x;
209     textInfo.y = y;
210     renderingContext2DModel_->SetFillText(paintState_, textInfo);
211 }
212 
StrokeText(const double x,const double y,const std::string & text)213 void NativeCanvasRenderer::StrokeText(const double x, const double y, const std::string& text)
214 {
215     FillTextInfo textInfo;
216     textInfo.text = text;
217     textInfo.x = x;
218     textInfo.y = y;
219     renderingContext2DModel_->SetStrokeText(paintState_, textInfo);
220 }
221 
MeasureText(const std::string & text)222 Metrics NativeCanvasRenderer::MeasureText(const std::string& text)
223 {
224     paintState_.SetTextStyle(style_);
225     double width = 0.0;
226     double height = 0.0;
227 
228     TextMetrics textMetrics = renderingContext2DModel_->GetMeasureTextMetrics(paintState_, text);
229     width = textMetrics.width;
230     height = textMetrics.height;
231 
232     Metrics metrics = { width, height };
233     return metrics;
234 }
235 
Stroke()236 void NativeCanvasRenderer::Stroke()
237 {
238     auto fillRule = CanvasFillRule::NONZERO;
239     renderingContext2DModel_->SetStrokeRuleForPath(fillRule);
240 }
241 
Stroke(const sptr<NativeCanvasPath> & canvasPath)242 void NativeCanvasRenderer::Stroke(const sptr<NativeCanvasPath>& canvasPath)
243 {
244     auto path = canvasPath->GetCanvasPath2d();
245     auto fillRule = CanvasFillRule::NONZERO;
246 
247     renderingContext2DModel_->SetStrokeRuleForPath2D(fillRule, path);
248 }
249 
BeginPath()250 void NativeCanvasRenderer::BeginPath()
251 {
252     renderingContext2DModel_->BeginPath();
253 }
254 
MoveTo(const double x,const double y)255 void NativeCanvasRenderer::MoveTo(const double x, const double y)
256 {
257     renderingContext2DModel_->MoveTo(x, y);
258 }
259 
LineTo(const double x,const double y)260 void NativeCanvasRenderer::LineTo(const double x, const double y)
261 {
262     renderingContext2DModel_->LineTo(x, y);
263 }
264 
ClosePath()265 void NativeCanvasRenderer::ClosePath()
266 {
267     renderingContext2DModel_->ClosePath();
268 }
269 
BezierCurveTo(const BezierCurveParam & param)270 void NativeCanvasRenderer::BezierCurveTo(const BezierCurveParam& param)
271 {
272     renderingContext2DModel_->BezierCurveTo(param);
273 }
274 
QuadraticCurveTo(const QuadraticCurveParam & param)275 void NativeCanvasRenderer::QuadraticCurveTo(const QuadraticCurveParam& param)
276 {
277     renderingContext2DModel_->QuadraticCurveTo(param);
278 }
279 
Arc(const ArcParam & param)280 void NativeCanvasRenderer::Arc(const ArcParam& param)
281 {
282     renderingContext2DModel_->Arc(param);
283 }
284 
ArcTo(const ArcToParam & param)285 void NativeCanvasRenderer::ArcTo(const ArcToParam& param)
286 {
287     renderingContext2DModel_->ArcTo(param);
288 }
289 
Ellipse(const EllipseParam & param)290 void NativeCanvasRenderer::Ellipse(const EllipseParam& param)
291 {
292     renderingContext2DModel_->Ellipse(param);
293 }
294 
NormalRect(const Rect & rect)295 void NativeCanvasRenderer::NormalRect(const Rect& rect)
296 {
297     renderingContext2DModel_->AddRect(rect);
298 }
299 
Fill()300 void NativeCanvasRenderer::Fill()
301 {
302     auto fillRule = CanvasFillRule::NONZERO;
303 
304     renderingContext2DModel_->SetFillRuleForPath(fillRule);
305 }
306 
Clip()307 void NativeCanvasRenderer::Clip()
308 {
309     auto fillRule = CanvasFillRule::NONZERO;
310     renderingContext2DModel_->SetClipRuleForPath(fillRule);
311 }
312 
Rotate(const double angle)313 void NativeCanvasRenderer::Rotate(const double angle)
314 {
315     renderingContext2DModel_->CanvasRendererRotate(angle);
316 }
317 
Scale(const double x,const double y)318 void NativeCanvasRenderer::Scale(const double x, const double y)
319 {
320     renderingContext2DModel_->CanvasRendererScale(x, y);
321 }
322 
Transform(const TransformParam & param)323 void NativeCanvasRenderer::Transform(const TransformParam& param)
324 {
325     renderingContext2DModel_->Transform(param);
326 }
327 
SetTransform(TransformParam param)328 void NativeCanvasRenderer::SetTransform(TransformParam param)
329 {
330     renderingContext2DModel_->SetTransform(param, true);
331 }
332 
Translate(const double x,const double y)333 void NativeCanvasRenderer::Translate(const double x, const double y)
334 {
335     renderingContext2DModel_->Translate(x, y);
336 }
337 
Restore()338 void NativeCanvasRenderer::Restore()
339 {
340     renderingContext2DModel_->Restore();
341 }
342 
Save()343 void NativeCanvasRenderer::Save()
344 {
345     renderingContext2DModel_->CanvasRendererSave();
346 }
347 
CreateLinearGradient(const double x0,const double y0,const double x1,const double y1)348 int64_t NativeCanvasRenderer::CreateLinearGradient(const double x0, const double y0, const double x1, const double y1)
349 {
350     Offset beginOffset = Offset(x0, y0);
351     Offset endOffset = Offset(x1, y1);
352 
353     Gradient gradient = Gradient();
354     gradient.SetType(GradientType::LINEAR);
355     gradient.SetBeginOffset(beginOffset);
356     gradient.SetEndOffset(endOffset);
357 
358     auto nativeCanvasGradient = FFIData::Create<NativeCanvasGradient>(gradient);
359     if (nativeCanvasGradient == nullptr) {
360         return FFI_ERROR_CODE;
361     }
362     return nativeCanvasGradient->GetID();
363 }
364 
CreateRadialGradient(const double x0,const double y0,const double r0,const double x1,const double y1,const double r1)365 int64_t NativeCanvasRenderer::CreateRadialGradient(
366     const double x0, const double y0, const double r0, const double x1, const double y1, const double r1)
367 {
368     Offset innerCenter = Offset(x0, y0);
369     Offset outerCenter = Offset(x1, y1);
370 
371     Gradient gradient = Gradient();
372     gradient.SetType(GradientType::RADIAL);
373     gradient.SetBeginOffset(innerCenter);
374     gradient.SetEndOffset(outerCenter);
375     gradient.SetInnerRadius(r0);
376     gradient.SetOuterRadius(r1);
377 
378     auto nativeCanvasGradient = FFIData::Create<NativeCanvasGradient>(gradient);
379     if (nativeCanvasGradient == nullptr) {
380         return FFI_ERROR_CODE;
381     }
382     return nativeCanvasGradient->GetID();
383 }
384 
DrawImage(const CanvasImage & image)385 void NativeCanvasRenderer::DrawImage(const CanvasImage& image)
386 {
387     ImageInfo imageInfo;
388     imageInfo.image = image;
389     imageInfo.isImage = true;
390     renderingContext2DModel_->DrawImage(imageInfo);
391 }
392 
DrawImage(const RefPtr<OHOS::Ace::PixelMap> & pixelMap,const CanvasImage & image)393 void NativeCanvasRenderer::DrawImage(const RefPtr<OHOS::Ace::PixelMap>& pixelMap, const CanvasImage& image)
394 {
395     ImageInfo imageInfo;
396     imageInfo.image = image;
397     imageInfo.isImage = false;
398     imageInfo.pixelMap = pixelMap;
399     renderingContext2DModel_->DrawPixelMap(imageInfo);
400 }
401 
GetImageData(const double left,const double top,const double width,const double height)402 std::unique_ptr<ImageData> NativeCanvasRenderer::GetImageData(
403     const double left, const double top, const double width, const double height)
404 {
405     std::unique_ptr<ImageData> canvasData;
406     ImageSize imageSize;
407     imageSize.left = left;
408     imageSize.top = top;
409     imageSize.width = width;
410     imageSize.height = height;
411     canvasData = renderingContext2DModel_->GetImageData(imageSize);
412     return canvasData;
413 }
414 
GetPixelMap(double left,double top,double width,double height)415 int64_t NativeCanvasRenderer::GetPixelMap(double left, double top, double width, double height)
416 {
417     auto finalHeight = static_cast<uint32_t>(std::abs(height));
418     auto finalWidth = static_cast<uint32_t>(std::abs(width));
419     if (finalHeight > 0 && finalWidth > (UINT32_MAX / finalHeight)) {
420         return 0;
421     }
422     ImageSize imageSize;
423     imageSize.left = left;
424     imageSize.top = top;
425     imageSize.width = finalWidth;
426     imageSize.height = finalHeight;
427     auto pixelmap = renderingContext2DModel_->GetPixelMap(imageSize);
428     if (pixelmap) {
429         auto ret = FFIData::Create<OHOS::Media::PixelMapImpl>(pixelmap->GetPixelMapSharedPtr());
430         if (ret == nullptr) {
431             return FFI_ERROR_CODE;
432         }
433         return ret->GetID();
434     } else {
435         LOGE("NativeCanvasRenderer GetPixelMap failed");
436         return 0;
437     }
438 }
439 } // namespace OHOS::Ace::Framework
440