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