• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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/declarative_frontend/jsview/js_canvas_renderer.h"
17 #include <cstdint>
18 
19 #include "bridge/common/utils/engine_helper.h"
20 #include "bridge/declarative_frontend/engine/js_converter.h"
21 #include "bridge/declarative_frontend/engine/jsi/jsi_types.h"
22 #include "bridge/declarative_frontend/jsview/js_canvas_pattern.h"
23 #include "bridge/declarative_frontend/jsview/js_offscreen_rendering_context.h"
24 #include "bridge/declarative_frontend/jsview/js_utils.h"
25 #include "bridge/declarative_frontend/jsview/models/canvas_renderer_model_impl.h"
26 #include "core/components_ng/pattern/canvas_renderer/canvas_renderer_model_ng.h"
27 
28 #ifdef PIXEL_MAP_SUPPORTED
29 #include "pixel_map.h"
30 #include "pixel_map_napi.h"
31 #endif
32 
33 namespace OHOS::Ace {
34 std::unique_ptr<CanvasRendererModel> CanvasRendererModel::instance_ = nullptr;
35 std::mutex CanvasRendererModel::mutex_;
GetInstance()36 CanvasRendererModel* CanvasRendererModel::GetInstance()
37 {
38     if (!instance_) {
39         std::lock_guard<std::mutex> lock(mutex_);
40         if (!instance_) {
41 #ifdef NG_BUILD
42             instance_.reset(new NG::CanvasRendererModelNG());
43 #else
44             if (Container::IsCurrentUseNewPipeline()) {
45                 instance_.reset(new NG::CanvasRendererModelNG());
46             } else {
47                 instance_.reset(new Framework::CanvasRendererModelImpl());
48             }
49 #endif
50         }
51     }
52     return instance_.get();
53 }
54 } // namespace OHOS::Ace
55 
56 namespace OHOS::Ace::Framework {
57 std::unordered_map<int32_t, std::shared_ptr<Pattern>> JSCanvasRenderer::pattern_;
58 unsigned int JSCanvasRenderer::patternCount_ = 0;
59 namespace {
60 
61 const std::set<std::string> FONT_WEIGHTS = {
62     "normal", "bold", "lighter", "bolder",
63     "100", "200", "300", "400", "500", "600", "700", "800", "900"
64 };
65 const std::set<std::string> FONT_STYLES = { "italic", "oblique", "normal" };
66 const std::set<std::string> FONT_FAMILIES = { "sans-serif", "serif", "monospace" };
67 const std::set<std::string> QUALITY_TYPE = { "low", "medium", "high" }; // Default value is low.
68 constexpr double DEFAULT_QUALITY = 0.92;
69 constexpr uint32_t COLOR_ALPHA_OFFSET = 24;
70 constexpr uint32_t COLOR_ALPHA_VALUE = 0xFF000000;
71 template<typename T>
ConvertStrToEnum(const char * key,const LinearMapNode<T> * map,size_t length,T defaultValue)72 inline T ConvertStrToEnum(const char* key, const LinearMapNode<T>* map, size_t length, T defaultValue)
73 {
74     int64_t index = BinarySearchFindIndex(map, length, key);
75     return index != -1 ? map[index].value : defaultValue;
76 }
77 
GetJsRectParam(const JSCallbackInfo & info)78 inline Rect GetJsRectParam(const JSCallbackInfo& info)
79 {
80     // 4 parameters: rect(x, y, width, height)
81     if (info.Length() != 4) {
82         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
83         return Rect();
84     }
85     double x = 0.0;
86     double y = 0.0;
87     double width = 0.0;
88     double height = 0.0;
89     JSViewAbstract::ParseJsDouble(info[0], x);
90     JSViewAbstract::ParseJsDouble(info[1], y);
91     JSViewAbstract::ParseJsDouble(info[2], width);
92     JSViewAbstract::ParseJsDouble(info[3], height);
93     x = SystemProperties::Vp2Px(x);
94     y = SystemProperties::Vp2Px(y);
95     width = SystemProperties::Vp2Px(width);
96     height = SystemProperties::Vp2Px(height);
97 
98     Rect rect = Rect(x, y, width, height);
99     return rect;
100 }
101 
ParseJsDoubleArray(const JSRef<JSVal> & jsValue,std::vector<double> & result)102 inline bool ParseJsDoubleArray(const JSRef<JSVal>& jsValue, std::vector<double>& result)
103 {
104     if (!jsValue->IsArray() && !jsValue->IsObject()) {
105         LOGE("arg is not array or Object.");
106         return false;
107     }
108 
109     if (jsValue->IsArray()) {
110         JSRef<JSArray> array = JSRef<JSArray>::Cast(jsValue);
111         for (size_t i = 0; i < array->Length(); i++) {
112             JSRef<JSVal> value = array->GetValueAt(i);
113             if (value->IsNumber()) {
114                 result.emplace_back(value->ToNumber<double>());
115             } else if (value->IsObject()) {
116                 double singleResInt;
117                 if (JSViewAbstract::ParseJsDouble(value, singleResInt)) {
118                     result.emplace_back(singleResInt);
119                 } else {
120                     return false;
121                 }
122             } else {
123                 return false;
124             }
125         }
126         return true;
127     }
128     return false;
129 }
130 
ParseJsInt(const JSRef<JSVal> & jsValue,int32_t & result)131 inline bool ParseJsInt(const JSRef<JSVal>& jsValue, int32_t& result)
132 {
133     if (!jsValue->IsNumber() && !jsValue->IsObject()) {
134         LOGE("arg is not number or Object.");
135         return false;
136     }
137 
138     if (jsValue->IsNumber()) {
139         LOGD("jsValue->IsNumber()");
140         result = jsValue->ToNumber<int32_t>();
141         return true;
142     }
143 
144     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
145     JSRef<JSVal> type = jsObj->GetProperty("type");
146     if (!type->IsNumber()) {
147         LOGW("type is not number");
148         return false;
149     }
150 
151     JSRef<JSVal> resId = jsObj->GetProperty("id");
152     if (!resId->IsNumber()) {
153         LOGW("resId is not number");
154         return false;
155     }
156     return false;
157 }
158 
159 const LinearMapNode<TextBaseline> BASELINE_TABLE[] = {
160     { "alphabetic", TextBaseline::ALPHABETIC },
161     { "bottom", TextBaseline::BOTTOM },
162     { "hanging", TextBaseline::HANGING },
163     { "ideographic", TextBaseline::IDEOGRAPHIC },
164     { "middle", TextBaseline::MIDDLE },
165     { "top", TextBaseline::TOP },
166 };
167 
ColorAlphaAdapt(uint32_t origin)168 uint32_t ColorAlphaAdapt(uint32_t origin)
169 {
170     uint32_t result = origin;
171     if ((origin >> COLOR_ALPHA_OFFSET) == 0) {
172         result = origin | COLOR_ALPHA_VALUE;
173     }
174     return result;
175 }
176 } // namespace
177 
JSCanvasRenderer()178 JSCanvasRenderer::JSCanvasRenderer()
179 {
180 }
181 
JsCreateLinearGradient(const JSCallbackInfo & info)182 void JSCanvasRenderer::JsCreateLinearGradient(const JSCallbackInfo& info)
183 {
184     JSRef<JSObject> pasteObj = JSClass<JSCanvasGradient>::NewInstance();
185     pasteObj->SetProperty("__type", "gradient");
186 
187     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber()
188         && info[3]->IsNumber()) {
189         double x0 = 0.0;
190         double y0 = 0.0;
191         double x1 = 0.0;
192         double y1 = 0.0;
193         JSViewAbstract::ParseJsDouble(info[0], x0);
194         JSViewAbstract::ParseJsDouble(info[1], y0);
195         JSViewAbstract::ParseJsDouble(info[2], x1);
196         JSViewAbstract::ParseJsDouble(info[3], y1);
197         x0 = SystemProperties::Vp2Px(x0);
198         y0 = SystemProperties::Vp2Px(y0);
199         x1 = SystemProperties::Vp2Px(x1);
200         y1 = SystemProperties::Vp2Px(y1);
201         Offset beginOffset = Offset(x0, y0);
202         Offset endOffset = Offset(x1, y1);
203 
204         Gradient* gradient = new Gradient();
205         gradient->SetType(GradientType::LINEAR);
206         gradient->SetBeginOffset(beginOffset);
207         gradient->SetEndOffset(endOffset);
208 
209         auto pasteData = Referenced::Claim(pasteObj->Unwrap<JSCanvasGradient>());
210         pasteData->SetGradient(gradient);
211         info.SetReturnValue(pasteObj);
212     }
213 }
214 
JsCreateRadialGradient(const JSCallbackInfo & info)215 void JSCanvasRenderer::JsCreateRadialGradient(const JSCallbackInfo& info)
216 {
217     JSRef<JSObject> pasteObj = JSClass<JSCanvasGradient>::NewInstance();
218     pasteObj->SetProperty("__type", "gradient");
219 
220     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber()
221         && info[3]->IsNumber()  && info[4]->IsNumber() && info[5]->IsNumber()) {
222         double startX = 0.0;
223         double startY = 0.0;
224         double startRadial = 0.0;
225         double endX = 0.0;
226         double endY = 0.0;
227         double endRadial = 0.0;
228         JSViewAbstract::ParseJsDouble(info[0], startX);
229         JSViewAbstract::ParseJsDouble(info[1], startY);
230         JSViewAbstract::ParseJsDouble(info[2], startRadial);
231         JSViewAbstract::ParseJsDouble(info[3], endX);
232         JSViewAbstract::ParseJsDouble(info[4], endY);
233         JSViewAbstract::ParseJsDouble(info[5], endRadial);
234         startX = SystemProperties::Vp2Px(startX);
235         startY = SystemProperties::Vp2Px(startY);
236         startRadial = SystemProperties::Vp2Px(startRadial);
237         endX = SystemProperties::Vp2Px(endX);
238         endY = SystemProperties::Vp2Px(endY);
239         endRadial = SystemProperties::Vp2Px(endRadial);
240         Offset innerCenter = Offset(startX, startY);
241         Offset outerCenter = Offset(endX, endY);
242 
243         Gradient* gradient = new Gradient();
244         gradient->SetType(GradientType::RADIAL);
245         gradient->SetBeginOffset(innerCenter);
246         gradient->SetEndOffset(outerCenter);
247         gradient->SetInnerRadius(startRadial);
248         gradient->SetOuterRadius(endRadial);
249 
250         auto pasteData = Referenced::Claim(pasteObj->Unwrap<JSCanvasGradient>());
251         pasteData->SetGradient(gradient);
252         info.SetReturnValue(pasteObj);
253     }
254 }
255 
JsCreateConicGradient(const JSCallbackInfo & info)256 void JSCanvasRenderer::JsCreateConicGradient(const JSCallbackInfo& info)
257 {
258     if (info.Length() != 3) {
259         LOGE("JsCreateConicGradient: The arg is wrong, it is supposed to have 3 arguments of number");
260         return;
261     }
262 
263     JSRef<JSObject> pasteObj = JSClass<JSCanvasGradient>::NewInstance();
264     pasteObj->SetProperty("__type", "gradient");
265 
266     // in radian
267     double startAngle = 0.0;
268     double x = 0.0;
269     double y = 0.0;
270     if (info[0]->IsNumber()) {
271         JSViewAbstract::ParseJsDouble(info[0], startAngle);
272     } else {
273         startAngle = 0.0;
274     }
275     if (info[1]->IsNumber()) {
276         JSViewAbstract::ParseJsDouble(info[1], x);
277     } else {
278         x = 0.0;
279     }
280     if (info[2]->IsNumber()) {
281         JSViewAbstract::ParseJsDouble(info[2], y);
282     } else {
283         y = 0.0;
284     }
285 
286     x = SystemProperties::Vp2Px(x);
287     y = SystemProperties::Vp2Px(y);
288     startAngle = fmod(startAngle, (2 * M_PI));
289 
290     Gradient* gradient = new Gradient();
291     gradient->SetType(GradientType::CONIC);
292     gradient->GetConicGradient().startAngle = AnimatableDimension(Dimension(startAngle));
293     gradient->GetConicGradient().centerX = AnimatableDimension(Dimension(x));
294     gradient->GetConicGradient().centerY = AnimatableDimension(Dimension(y));
295 
296     auto pasteData = Referenced::Claim(pasteObj->Unwrap<JSCanvasGradient>());
297     pasteData->SetGradient(gradient);
298     info.SetReturnValue(pasteObj);
299 }
300 
JsFillText(const JSCallbackInfo & info)301 void JSCanvasRenderer::JsFillText(const JSCallbackInfo& info)
302 {
303     if (info.Length() < 1) {
304         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
305         return;
306     }
307 
308     if (info[0]->IsString() && info[1]->IsNumber() && info[2]->IsNumber()) {
309         double x = 0.0;
310         double y = 0.0;
311         std::string text = "";
312         JSViewAbstract::ParseJsString(info[0], text);
313         JSViewAbstract::ParseJsDouble(info[1], x);
314         JSViewAbstract::ParseJsDouble(info[2], y);
315         x = SystemProperties::Vp2Px(x);
316         y = SystemProperties::Vp2Px(y);
317         std::optional<double> maxWidth;
318         if (info.Length() >= 4) {
319             double width = 0.0;
320             if (info[3]->IsUndefined()) {
321                 width = FLT_MAX;
322             } else if (info[3]->IsNumber()) {
323                 JSViewAbstract::ParseJsDouble(info[3], width);
324                 width = SystemProperties::Vp2Px(width);
325             }
326             maxWidth = width;
327         }
328 
329         BaseInfo baseInfo;
330         baseInfo.canvasPattern = canvasPattern_;
331         baseInfo.offscreenPattern = offscreenPattern_;
332         baseInfo.isOffscreen = isOffscreen_;
333         baseInfo.paintState = paintState_;
334 
335         FillTextInfo fillTextInfo;
336         fillTextInfo.text = text;
337         fillTextInfo.x = x;
338         fillTextInfo.y = y;
339         fillTextInfo.maxWidth = maxWidth;
340 
341         CanvasRendererModel::GetInstance()->SetFillText(baseInfo, fillTextInfo);
342     }
343 }
344 
JsStrokeText(const JSCallbackInfo & info)345 void JSCanvasRenderer::JsStrokeText(const JSCallbackInfo& info)
346 {
347     if (info.Length() < 1) {
348         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
349         return;
350     }
351 
352     if (info[0]->IsString() && info[1]->IsNumber() && info[2]->IsNumber()) {
353         double x = 0.0;
354         double y = 0.0;
355         std::string text = "";
356         JSViewAbstract::ParseJsString(info[0], text);
357         JSViewAbstract::ParseJsDouble(info[1], x);
358         JSViewAbstract::ParseJsDouble(info[2], y);
359         x = SystemProperties::Vp2Px(x);
360         y = SystemProperties::Vp2Px(y);
361         std::optional<double> maxWidth;
362         if (info.Length() >= 4) {
363             double width = 0.0;
364             if (info[3]->IsUndefined()) {
365                 width = FLT_MAX;
366             } else if (info[3]->IsNumber()) {
367                 JSViewAbstract::ParseJsDouble(info[3], width);
368                 width = SystemProperties::Vp2Px(width);
369             }
370             maxWidth = width;
371         }
372 
373         BaseInfo baseInfo;
374         baseInfo.canvasPattern = canvasPattern_;
375         baseInfo.offscreenPattern = offscreenPattern_;
376         baseInfo.isOffscreen = isOffscreen_;
377         baseInfo.paintState = paintState_;
378 
379         FillTextInfo fillTextInfo;
380         fillTextInfo.text = text;
381         fillTextInfo.x = x;
382         fillTextInfo.y = y;
383         fillTextInfo.maxWidth = maxWidth;
384 
385         CanvasRendererModel::GetInstance()->SetStrokeText(baseInfo, fillTextInfo);
386     }
387 }
388 
SetAntiAlias()389 void JSCanvasRenderer::SetAntiAlias()
390 {
391     BaseInfo baseInfo;
392     baseInfo.canvasPattern = canvasPattern_;
393     baseInfo.offscreenPattern = offscreenPattern_;
394     baseInfo.isOffscreen = isOffscreen_;
395     baseInfo.anti = anti_;
396 
397     CanvasRendererModel::GetInstance()->SetAntiAlias(baseInfo);
398 }
399 
JsSetFont(const JSCallbackInfo & info)400 void JSCanvasRenderer::JsSetFont(const JSCallbackInfo& info)
401 {
402     if (info.Length() < 1) {
403         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
404         return;
405     }
406     std::string fontStr = "";
407     JSViewAbstract::ParseJsString(info[0], fontStr);
408 
409     BaseInfo baseInfo;
410     baseInfo.canvasPattern = canvasPattern_;
411     baseInfo.offscreenPattern = offscreenPattern_;
412     baseInfo.isOffscreen = isOffscreen_;
413 
414     std::vector<std::string> fontProps;
415     StringUtils::StringSplitter(fontStr.c_str(), ' ', fontProps);
416     bool updateFontStyle = false;
417     for (const auto& fontProp : fontProps) {
418         if (FONT_WEIGHTS.find(fontProp) != FONT_WEIGHTS.end()) {
419             auto weight = ConvertStrToFontWeight(fontProp);
420             style_.SetFontWeight(weight);
421             CanvasRendererModel::GetInstance()->SetFontWeight(baseInfo, weight);
422         } else if (FONT_STYLES.find(fontProp) != FONT_STYLES.end()) {
423             updateFontStyle = true;
424             auto fontStyle = ConvertStrToFontStyle(fontProp);
425             style_.SetFontStyle(fontStyle);
426             CanvasRendererModel::GetInstance()->SetFontStyle(baseInfo, fontStyle);
427         } else if (FONT_FAMILIES.find(fontProp) != FONT_FAMILIES.end()) {
428             auto families = ConvertStrToFontFamilies(fontProp);
429             style_.SetFontFamilies(families);
430             CanvasRendererModel::GetInstance()->SetFontFamilies(baseInfo, families);
431         } else if (fontProp.find("px") != std::string::npos || fontProp.find("vp") != std::string::npos) {
432             Dimension size;
433             if (fontProp.find("vp") != std::string::npos) {
434                 size = Dimension(StringToDimension(fontProp).ConvertToPx());
435             } else {
436                 std::string fontSize = fontProp.substr(0, fontProp.size() - 2);
437                 size = Dimension(StringToDouble(fontProp));
438             }
439             style_.SetFontSize(size);
440             CanvasRendererModel::GetInstance()->SetFontSize(baseInfo, size);
441         } else {
442             LOGW("parse text error");
443         }
444     }
445     if (!updateFontStyle) {
446         CanvasRendererModel::GetInstance()->SetFontStyle(baseInfo, FontStyle::NORMAL);
447     }
448 }
449 
JsGetFont(const JSCallbackInfo & info)450 void JSCanvasRenderer::JsGetFont(const JSCallbackInfo& info)
451 {
452     return;
453 }
454 
JsGetFillStyle(const JSCallbackInfo & info)455 void JSCanvasRenderer::JsGetFillStyle(const JSCallbackInfo& info)
456 {
457     return;
458 }
459 
JsGetStrokeStyle(const JSCallbackInfo & info)460 void JSCanvasRenderer::JsGetStrokeStyle(const JSCallbackInfo& info)
461 {
462     return;
463 }
464 
JsGetLineCap(const JSCallbackInfo & info)465 void JSCanvasRenderer::JsGetLineCap(const JSCallbackInfo& info)
466 {
467     return;
468 }
469 
JsGetLineDash(const JSCallbackInfo & info)470 void JSCanvasRenderer::JsGetLineDash(const JSCallbackInfo& info)
471 {
472     BaseInfo baseInfo;
473     baseInfo.canvasPattern = canvasPattern_;
474     baseInfo.offscreenPattern = offscreenPattern_;
475     baseInfo.isOffscreen = isOffscreen_;
476 
477     std::vector<double> lineDash = CanvasRendererModel::GetInstance()->GetLineDash(baseInfo);
478 
479     JSRef<JSObject> lineDashObj = JSRef<JSObject>::New();
480     for (size_t i = 0; i < lineDash.size(); i++) {
481         lineDashObj->SetProperty<double>(std::to_string(i).c_str(), lineDash[i]);
482     }
483     info.SetReturnValue(lineDashObj);
484 }
485 
JsGetLineJoin(const JSCallbackInfo & info)486 void JSCanvasRenderer::JsGetLineJoin(const JSCallbackInfo& info)
487 {
488     return;
489 }
490 
JsGetMiterLimit(const JSCallbackInfo & info)491 void JSCanvasRenderer::JsGetMiterLimit(const JSCallbackInfo& info)
492 {
493     return;
494 }
495 
JsGetLineWidth(const JSCallbackInfo & info)496 void JSCanvasRenderer::JsGetLineWidth(const JSCallbackInfo& info)
497 {
498     return;
499 }
500 
JsGetTextAlign(const JSCallbackInfo & info)501 void JSCanvasRenderer::JsGetTextAlign(const JSCallbackInfo& info)
502 {
503     return;
504 }
505 
JsGetTextBaseline(const JSCallbackInfo & info)506 void JSCanvasRenderer::JsGetTextBaseline(const JSCallbackInfo& info)
507 {
508     return;
509 }
510 
JsGetGlobalAlpha(const JSCallbackInfo & info)511 void JSCanvasRenderer::JsGetGlobalAlpha(const JSCallbackInfo& info)
512 {
513     return;
514 }
515 
JsGetGlobalCompositeOperation(const JSCallbackInfo & info)516 void JSCanvasRenderer::JsGetGlobalCompositeOperation(const JSCallbackInfo& info)
517 {
518     return;
519 }
520 
JsGetLineDashOffset(const JSCallbackInfo & info)521 void JSCanvasRenderer::JsGetLineDashOffset(const JSCallbackInfo& info)
522 {
523     return;
524 }
525 
JsGetShadowBlur(const JSCallbackInfo & info)526 void JSCanvasRenderer::JsGetShadowBlur(const JSCallbackInfo& info)
527 {
528     return;
529 }
530 
JsGetShadowColor(const JSCallbackInfo & info)531 void JSCanvasRenderer::JsGetShadowColor(const JSCallbackInfo& info)
532 {
533     return;
534 }
535 
JsGetShadowOffsetX(const JSCallbackInfo & info)536 void JSCanvasRenderer::JsGetShadowOffsetX(const JSCallbackInfo& info)
537 {
538     return;
539 }
540 
JsGetShadowOffsetY(const JSCallbackInfo & info)541 void JSCanvasRenderer::JsGetShadowOffsetY(const JSCallbackInfo& info)
542 {
543     return;
544 }
545 
JsGetImageSmoothingEnabled(const JSCallbackInfo & info)546 void JSCanvasRenderer::JsGetImageSmoothingEnabled(const JSCallbackInfo& info)
547 {
548     return;
549 }
550 
JsGetImageSmoothingQuality(const JSCallbackInfo & info)551 void JSCanvasRenderer::JsGetImageSmoothingQuality(const JSCallbackInfo& info)
552 {
553     return;
554 }
555 
ParseFillGradient(const JSCallbackInfo & info)556 void JSCanvasRenderer::ParseFillGradient(const JSCallbackInfo& info)
557 {
558     auto* jSCanvasGradient = JSRef<JSObject>::Cast(info[0])->Unwrap<JSCanvasGradient>();
559     if (!jSCanvasGradient) {
560         return;
561     }
562     Gradient* gradient = jSCanvasGradient->GetGradient();
563     if (!gradient) {
564         return;
565     }
566 
567     BaseInfo baseInfo;
568     baseInfo.canvasPattern = canvasPattern_;
569     baseInfo.offscreenPattern = offscreenPattern_;
570     baseInfo.isOffscreen = isOffscreen_;
571 
572     CanvasRendererModel::GetInstance()->SetFillGradient(baseInfo, *gradient);
573 }
574 
ParseFillPattern(const JSCallbackInfo & info)575 void JSCanvasRenderer::ParseFillPattern(const JSCallbackInfo& info)
576 {
577     if (info.Length() < 1 || !info[0]->IsObject()) {
578         LOGE("The argument is wrong, it is supposed to have at least 1 arguments"
579             "and the first argument must be a object.");
580         return;
581     }
582     auto* jSCanvasPattern = JSRef<JSObject>::Cast(info[0])->Unwrap<JSCanvasPattern>();
583     CHECK_NULL_VOID(jSCanvasPattern);
584     int32_t id = jSCanvasPattern->GetId();
585 
586     BaseInfo baseInfo;
587     baseInfo.canvasPattern = canvasPattern_;
588     baseInfo.offscreenPattern = offscreenPattern_;
589     baseInfo.isOffscreen = isOffscreen_;
590 
591     CanvasRendererModel::GetInstance()->SetFillPattern(baseInfo, GetPatternPtr(id));
592 }
593 
JsSetFillStyle(const JSCallbackInfo & info)594 void JSCanvasRenderer::JsSetFillStyle(const JSCallbackInfo& info)
595 {
596     if (info.Length() < 1) {
597         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
598         return;
599     }
600 
601     BaseInfo baseInfo;
602     baseInfo.canvasPattern = canvasPattern_;
603     baseInfo.offscreenPattern = offscreenPattern_;
604     baseInfo.isOffscreen = isOffscreen_;
605 
606     if (info[0]->IsString()) {
607         Color color;
608         if (!JSViewAbstract::CheckColor(info[0], color, "CanvasRenderer", "fillStyle")) {
609             return;
610         }
611 
612         CanvasRendererModel::GetInstance()->SetFillColor(baseInfo, color, true);
613         return;
614     }
615     if (!info[0]->IsObject()) {
616         LOGE("The arg is not Object.");
617         return;
618     }
619     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
620     JSRef<JSVal> typeValue = obj->GetProperty("__type");
621     std::string type = "";
622     JSViewAbstract::ParseJsString(typeValue, type);
623     if (type == "gradient") {
624         ParseFillGradient(info);
625     } else if (type == "pattern") {
626         ParseFillPattern(info);
627     }
628     if (info[0]->IsNumber()) {
629         auto color = Color(ColorAlphaAdapt(info[0]->ToNumber<uint32_t>()));
630         CanvasRendererModel::GetInstance()->SetFillColor(baseInfo, color, false);
631     } else {
632         LOGW("unsupported function for fill style.");
633     }
634 }
635 
ParseStorkeGradient(const JSCallbackInfo & info)636 void JSCanvasRenderer::ParseStorkeGradient(const JSCallbackInfo& info)
637 {
638     if (info.Length() < 1 || !info[0]->IsObject()) {
639         LOGE("The argument is wrong, it is supposed to have at least 1 arguments"
640             "and the first argument must be a object.");
641         return;
642     }
643     auto* jSCanvasGradient = JSRef<JSObject>::Cast(info[0])->Unwrap<JSCanvasGradient>();
644     if (!jSCanvasGradient) {
645         return;
646     }
647     Gradient* gradient = jSCanvasGradient->GetGradient();
648     if (!gradient) {
649         return;
650     }
651 
652     BaseInfo baseInfo;
653     baseInfo.canvasPattern = canvasPattern_;
654     baseInfo.offscreenPattern = offscreenPattern_;
655     baseInfo.isOffscreen = isOffscreen_;
656 
657     CanvasRendererModel::GetInstance()->SetStrokeGradient(baseInfo, *gradient);
658 }
659 
ParseStrokePattern(const JSCallbackInfo & info)660 void JSCanvasRenderer::ParseStrokePattern(const JSCallbackInfo& info)
661 {
662     if (info.Length() < 1 || !info[0]->IsObject()) {
663         LOGE("The argument is wrong, it is supposed to have at least 1 arguments"
664             "and the first argument must be a object.");
665         return;
666     }
667     auto* jSCanvasPattern = JSRef<JSObject>::Cast(info[0])->Unwrap<JSCanvasPattern>();
668     CHECK_NULL_VOID(jSCanvasPattern);
669     int32_t id = jSCanvasPattern->GetId();
670 
671     BaseInfo baseInfo;
672     baseInfo.canvasPattern = canvasPattern_;
673     baseInfo.offscreenPattern = offscreenPattern_;
674     baseInfo.isOffscreen = isOffscreen_;
675 
676     CanvasRendererModel::GetInstance()->SetStrokePattern(baseInfo, GetPatternPtr(id));
677 }
678 
JsSetStrokeStyle(const JSCallbackInfo & info)679 void JSCanvasRenderer::JsSetStrokeStyle(const JSCallbackInfo& info)
680 {
681     if (info.Length() < 1) {
682         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
683         return;
684     }
685 
686     BaseInfo baseInfo;
687     baseInfo.canvasPattern = canvasPattern_;
688     baseInfo.offscreenPattern = offscreenPattern_;
689     baseInfo.isOffscreen = isOffscreen_;
690 
691     if (info[0]->IsString()) {
692         Color color;
693         if (!JSViewAbstract::CheckColor(info[0], color, "CanvasRenderer", "strokeStyle")) {
694             return;
695         }
696         CanvasRendererModel::GetInstance()->SetStrokeColor(baseInfo, color, true);
697         return;
698     }
699     if (!info[0]->IsObject()) {
700         LOGE("The arg is not Object.");
701         return;
702     }
703     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
704     JSRef<JSVal> typeValue = obj->GetProperty("__type");
705     std::string type;
706     JSViewAbstract::ParseJsString(typeValue, type);
707     if (type == "gradient") {
708         ParseStorkeGradient(info);
709     } else if (type == "pattern") {
710         ParseStrokePattern(info);
711     }
712     if (info[0]->IsNumber()) {
713         auto color = Color(ColorAlphaAdapt(info[0]->ToNumber<uint32_t>()));
714         CanvasRendererModel::GetInstance()->SetStrokeColor(baseInfo, color, false);
715     } else {
716         LOGW("unsupported function for stroke style.");
717     }
718 }
719 
JsMakePath2D(const JSCallbackInfo & info)720 RefPtr<CanvasPath2D> JSCanvasRenderer::JsMakePath2D(const JSCallbackInfo& info)
721 {
722     if (info.Length() == 1) {
723         if (info[0]->IsString()) {
724             std::string capStr = "";
725             JSViewAbstract::ParseJsString(info[0], capStr);
726             return AceType::MakeRefPtr<CanvasPath2D>(capStr);
727         }
728     }
729     // Example: ctx.createPath2D()
730     return AceType::MakeRefPtr<CanvasPath2D>();
731 }
732 
JsDrawImage(const JSCallbackInfo & info)733 void JSCanvasRenderer::JsDrawImage(const JSCallbackInfo& info)
734 {
735     CanvasImage image;
736     double imgWidth = 0.0;
737     double imgHeight = 0.0;
738     RefPtr<PixelMap> pixelMap = nullptr;
739     bool isImage = false;
740     if (!info[0]->IsObject()) {
741         LOGE("The arg is not Object or String.");
742         return;
743     }
744     JSRenderImage* jsImage = JSRef<JSObject>::Cast(info[0])->Unwrap<JSRenderImage>();
745     if (jsImage) {
746         isImage = true;
747         std::string imageValue = jsImage->GetSrc();
748         image.src = imageValue;
749         imgWidth = jsImage->GetWidth();
750         imgHeight = jsImage->GetHeight();
751 
752         auto closeCallback = [weak = AceType::WeakClaim(this), imageValue]() {
753             auto jsCanvasRenderer = weak.Upgrade();
754             CHECK_NULL_VOID(jsCanvasRenderer);
755             jsCanvasRenderer->JsCloseImageBitmap(imageValue);
756         };
757         jsImage->SetCloseCallback(closeCallback);
758     } else {
759 #if !defined(PREVIEW)
760         pixelMap = CreatePixelMapFromNapiValue(info[0]);
761 #endif
762         if (!pixelMap) {
763             LOGE("pixelMap is null");
764             return;
765         }
766     }
767     ExtractInfoToImage(image, info, isImage);
768 
769     BaseInfo baseInfo;
770     baseInfo.canvasPattern = canvasPattern_;
771     baseInfo.offscreenPattern = offscreenPattern_;
772     baseInfo.isOffscreen = isOffscreen_;
773 
774     ImageInfo imageInfo;
775     imageInfo.image = image;
776     imageInfo.imgWidth = imgWidth;
777     imageInfo.imgHeight = imgHeight;
778     imageInfo.pixelMap = pixelMap;
779     imageInfo.isImage = isImage;
780 
781     CanvasRendererModel::GetInstance()->DrawImage(baseInfo, imageInfo);
782 }
783 
ExtractInfoToImage(CanvasImage & image,const JSCallbackInfo & info,bool isImage)784 void JSCanvasRenderer::ExtractInfoToImage(CanvasImage& image, const JSCallbackInfo& info, bool isImage)
785 {
786     switch (info.Length()) {
787         case 3:
788             image.flag = 0;
789             JSViewAbstract::ParseJsDouble(info[1], image.dx);
790             JSViewAbstract::ParseJsDouble(info[2], image.dy);
791             image.dx = SystemProperties::Vp2Px(image.dx);
792             image.dy = SystemProperties::Vp2Px(image.dy);
793             break;
794         // 5 parameters: drawImage(image, dx, dy, dWidth, dHeight)
795         case 5:
796             image.flag = 1;
797             JSViewAbstract::ParseJsDouble(info[1], image.dx);
798             JSViewAbstract::ParseJsDouble(info[2], image.dy);
799             JSViewAbstract::ParseJsDouble(info[3], image.dWidth);
800             JSViewAbstract::ParseJsDouble(info[4], image.dHeight);
801             image.dx = SystemProperties::Vp2Px(image.dx);
802             image.dy = SystemProperties::Vp2Px(image.dy);
803             image.dWidth = SystemProperties::Vp2Px(image.dWidth);
804             image.dHeight = SystemProperties::Vp2Px(image.dHeight);
805             break;
806         // 9 parameters: drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
807         case 9:
808             image.flag = 2;
809             JSViewAbstract::ParseJsDouble(info[1], image.sx);
810             JSViewAbstract::ParseJsDouble(info[2], image.sy);
811             JSViewAbstract::ParseJsDouble(info[3], image.sWidth);
812             JSViewAbstract::ParseJsDouble(info[4], image.sHeight);
813             JSViewAbstract::ParseJsDouble(info[5], image.dx);
814             JSViewAbstract::ParseJsDouble(info[6], image.dy);
815             JSViewAbstract::ParseJsDouble(info[7], image.dWidth);
816             JSViewAbstract::ParseJsDouble(info[8], image.dHeight);
817             if (isImage) {
818                 image.sx = SystemProperties::Vp2Px(image.sx);
819                 image.sy = SystemProperties::Vp2Px(image.sy);
820                 image.sWidth = SystemProperties::Vp2Px(image.sWidth);
821                 image.sHeight = SystemProperties::Vp2Px(image.sHeight);
822             }
823             image.dx = SystemProperties::Vp2Px(image.dx);
824             image.dy = SystemProperties::Vp2Px(image.dy);
825             image.dWidth = SystemProperties::Vp2Px(image.dWidth);
826             image.dHeight = SystemProperties::Vp2Px(image.dHeight);
827             break;
828         default:
829             break;
830     }
831 }
832 
JsCreatePattern(const JSCallbackInfo & info)833 void JSCanvasRenderer::JsCreatePattern(const JSCallbackInfo& info)
834 {
835     if (info.Length() != 2) {
836         LOGE("The argv is wrong.");
837         return;
838     }
839     if (info[0]->IsObject()) {
840         auto* jsImage = JSRef<JSObject>::Cast(info[0])->Unwrap<JSRenderImage>();
841         if (jsImage == nullptr) {
842             LOGE("jsImage is null");
843             return;
844         }
845         std::string imageSrc = jsImage->GetSrc();
846         double imgWidth = jsImage->GetWidth();
847         double imgHeight = jsImage->GetHeight();
848         std::string repeat;
849 
850         JSViewAbstract::ParseJsString(info[1], repeat);
851         auto pattern = std::make_shared<Pattern>();
852         pattern->SetImgSrc(imageSrc);
853         pattern->SetImageWidth(imgWidth);
854         pattern->SetImageHeight(imgHeight);
855         pattern->SetRepetition(repeat);
856         pattern_[patternCount_] = pattern;
857 
858         JSRef<JSObject> obj = JSClass<JSCanvasPattern>::NewInstance();
859         obj->SetProperty("__type", "pattern");
860         auto canvasPattern = Referenced::Claim(obj->Unwrap<JSCanvasPattern>());
861         canvasPattern->SetCanvasRenderer(AceType::WeakClaim(this));
862         canvasPattern->SetId(patternCount_);
863         patternCount_++;
864         info.SetReturnValue(obj);
865     }
866 }
867 
JsCreateImageData(const JSCallbackInfo & info)868 void JSCanvasRenderer::JsCreateImageData(const JSCallbackInfo& info)
869 {
870     double width = 0;
871     double height = 0;
872 
873     if (info.Length() == 2) {
874         JSViewAbstract::ParseJsDouble(info[0], width);
875         JSViewAbstract::ParseJsDouble(info[1], height);
876         width = SystemProperties::Vp2Px(width);
877         height = SystemProperties::Vp2Px(height);
878     }
879     if (info.Length() == 1 && info[0]->IsObject()) {
880         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
881         JSRef<JSVal> widthValue = obj->GetProperty("width");
882         JSRef<JSVal> heightValue = obj->GetProperty("height");
883         JSViewAbstract::ParseJsDouble(widthValue, width);
884         JSViewAbstract::ParseJsDouble(heightValue, height);
885     }
886 
887     JSRef<JSArrayBuffer> arrayBuffer = JSRef<JSArrayBuffer>::New(width * height * 4);
888     // return the black image
889     auto* buffer = static_cast<uint32_t*>(arrayBuffer->GetBuffer());
890     for (uint32_t idx = 0; idx < width * height; ++idx) {
891         buffer[idx] = 0xffffffff;
892     }
893 
894     JSRef<JSUint8ClampedArray> colorArray =
895         JSRef<JSUint8ClampedArray>::New(arrayBuffer->GetLocalHandle(), 0, arrayBuffer->ByteLength());
896 
897     auto retObj = JSRef<JSObject>::New();
898     retObj->SetProperty("width", width);
899     retObj->SetProperty("height", height);
900     retObj->SetPropertyObject("data", colorArray);
901     info.SetReturnValue(retObj);
902 }
903 
JsPutImageData(const JSCallbackInfo & info)904 void JSCanvasRenderer::JsPutImageData(const JSCallbackInfo& info)
905 {
906     if (info.Length() < 1 || !info[0]->IsObject()) {
907         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
908         return;
909     }
910     int32_t width = 0;
911     int32_t height = 0;
912     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
913     JSRef<JSVal> widthValue = obj->GetProperty("width");
914     JSRef<JSVal> heightValue = obj->GetProperty("height");
915     ParseJsInt(widthValue, width);
916     ParseJsInt(heightValue, height);
917 
918     ImageData imageData;
919     std::vector<uint8_t> array;
920     ParseImageData(info, imageData, array);
921 
922     for (int32_t i = std::max(imageData.dirtyY, 0); i < imageData.dirtyY + imageData.dirtyHeight; ++i) {
923         for (int32_t j = std::max(imageData.dirtyX, 0); j < imageData.dirtyX + imageData.dirtyWidth; ++j) {
924             uint32_t idx = 4 * (j + width * i);
925             if (array.size() > idx + 3) {
926                 imageData.data.emplace_back(
927                     Color::FromARGB(array[idx + 3], array[idx], array[idx + 1], array[idx + 2]));
928             }
929         }
930     }
931 
932     BaseInfo baseInfo;
933     baseInfo.canvasPattern = canvasPattern_;
934     baseInfo.offscreenPattern = offscreenPattern_;
935     baseInfo.isOffscreen = isOffscreen_;
936 
937     CanvasRendererModel::GetInstance()->PutImageData(baseInfo, imageData);
938 }
939 
ParseImageData(const JSCallbackInfo & info,ImageData & imageData,std::vector<uint8_t> & array)940 void JSCanvasRenderer::ParseImageData(const JSCallbackInfo& info, ImageData& imageData, std::vector<uint8_t>& array)
941 {
942     int32_t width = 0;
943     int32_t height = 0;
944 
945     if (info[0]->IsObject()) {
946         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
947         JSRef<JSVal> widthValue = obj->GetProperty("width");
948         JSRef<JSVal> heightValue = obj->GetProperty("height");
949         JSRef<JSVal> dataValue = obj->GetProperty("data");
950         ParseJsInt(widthValue, width);
951         ParseJsInt(heightValue, height);
952         if (dataValue->IsUint8ClampedArray()) {
953             JSRef<JSUint8ClampedArray> colorArray = JSRef<JSUint8ClampedArray>::Cast(dataValue);
954             auto arrayBuffer = colorArray->GetArrayBuffer();
955             auto* buffer = static_cast<uint8_t*>(arrayBuffer->GetBuffer());
956             for (auto idx = 0; idx < arrayBuffer->ByteLength(); ++idx) {
957                 array.emplace_back(buffer[idx]);
958             }
959         }
960     }
961 
962     Dimension value;
963     if (info[1]->IsString()) {
964         std::string imageDataXStr = "";
965         JSViewAbstract::ParseJsString(info[1], imageDataXStr);
966         value = Dimension(StringToDimension(imageDataXStr).ConvertToPx());
967         imageData.x = value.Value();
968     } else {
969         ParseJsInt(info[1], imageData.x);
970         imageData.x = SystemProperties::Vp2Px(imageData.x);
971     }
972     if (info[2]->IsString()) {
973         std::string imageDataYStr = "";
974         JSViewAbstract::ParseJsString(info[2], imageDataYStr);
975         value = Dimension(StringToDimension(imageDataYStr).ConvertToPx());
976         imageData.y = value.Value();
977     } else {
978         ParseJsInt(info[2], imageData.y);
979         imageData.y = SystemProperties::Vp2Px(imageData.y);
980     }
981 
982     imageData.dirtyWidth = width;
983     imageData.dirtyHeight = height;
984 
985     if (info.Length() == 7) {
986         ParseImageDataAsStr(info, imageData);
987     }
988 
989     imageData.dirtyWidth = imageData.dirtyX < 0 ? std::min(imageData.dirtyX + imageData.dirtyWidth, width)
990                                                 : std::min(width - imageData.dirtyX, imageData.dirtyWidth);
991     imageData.dirtyHeight = imageData.dirtyY < 0 ? std::min(imageData.dirtyY + imageData.dirtyHeight, height)
992                                                  : std::min(height - imageData.dirtyY, imageData.dirtyHeight);
993 }
994 
ParseImageDataAsStr(const JSCallbackInfo & info,ImageData & imageData)995 void JSCanvasRenderer::ParseImageDataAsStr(const JSCallbackInfo& info, ImageData& imageData)
996 {
997     Dimension value;
998     if (info[3]->IsString()) {
999         std::string imageDataDirtyXStr = "";
1000         JSViewAbstract::ParseJsString(info[3], imageDataDirtyXStr);
1001         value = Dimension(StringToDimension(imageDataDirtyXStr).ConvertToPx());
1002         imageData.dirtyX = value.Value();
1003     } else {
1004         ParseJsInt(info[3], imageData.dirtyX);
1005         imageData.dirtyX = SystemProperties::Vp2Px(imageData.dirtyX);
1006     }
1007     if (info[4]->IsString()) {
1008         std::string imageDataDirtyYStr = "";
1009         JSViewAbstract::ParseJsString(info[4], imageDataDirtyYStr);
1010         value = Dimension(StringToDimension(imageDataDirtyYStr).ConvertToPx());
1011         imageData.dirtyY = value.Value();
1012     } else {
1013         ParseJsInt(info[4], imageData.dirtyY);
1014         imageData.dirtyY = SystemProperties::Vp2Px(imageData.dirtyY);
1015     }
1016     if (info[5]->IsString()) {
1017         std::string imageDataDirtWidth = "";
1018         JSViewAbstract::ParseJsString(info[5], imageDataDirtWidth);
1019         value = Dimension(StringToDimension(imageDataDirtWidth).ConvertToPx());
1020         imageData.dirtyWidth = value.Value();
1021     } else {
1022         ParseJsInt(info[5], imageData.dirtyWidth);
1023         imageData.dirtyWidth = SystemProperties::Vp2Px(imageData.dirtyWidth);
1024     }
1025     if (info[6]->IsString()) {
1026         std::string imageDataDirtyHeight = "";
1027         JSViewAbstract::ParseJsString(info[6], imageDataDirtyHeight);
1028         value = Dimension(StringToDimension(imageDataDirtyHeight).ConvertToPx());
1029         imageData.dirtyHeight = value.Value();
1030     } else {
1031         ParseJsInt(info[6], imageData.dirtyHeight);
1032         imageData.dirtyHeight = SystemProperties::Vp2Px(imageData.dirtyHeight);
1033     }
1034 }
1035 
JsCloseImageBitmap(const std::string & src)1036 void JSCanvasRenderer::JsCloseImageBitmap(const std::string& src)
1037 {
1038     BaseInfo baseInfo;
1039     baseInfo.canvasPattern = canvasPattern_;
1040     baseInfo.offscreenPattern = offscreenPattern_;
1041     baseInfo.isOffscreen = isOffscreen_;
1042 
1043     CanvasRendererModel::GetInstance()->CloseImageBitmap(baseInfo, src);
1044 }
1045 
JsGetImageData(const JSCallbackInfo & info)1046 void JSCanvasRenderer::JsGetImageData(const JSCallbackInfo& info)
1047 {
1048     double fLeft = 0.0;
1049     double fTop = 0.0;
1050     double fWidth = 0.0;
1051     double fHeight = 0.0;
1052     uint32_t finalWidth = 0;
1053     uint32_t finalHeight = 0;
1054     int32_t left = 0;
1055     int32_t top = 0;
1056     int32_t width = 0;
1057     int32_t height = 0;
1058 
1059     JSViewAbstract::ParseJsDouble(info[0], fLeft);
1060     JSViewAbstract::ParseJsDouble(info[1], fTop);
1061     JSViewAbstract::ParseJsDouble(info[2], fWidth);
1062     JSViewAbstract::ParseJsDouble(info[3], fHeight);
1063 
1064     left = fLeft;
1065     top = fTop;
1066     width = fWidth;
1067     height = fHeight;
1068 
1069     left = SystemProperties::Vp2Px(left);
1070     top = SystemProperties::Vp2Px(top);
1071     width = SystemProperties::Vp2Px(width);
1072     height = SystemProperties::Vp2Px(height);
1073 
1074     finalHeight = static_cast<uint32_t>(std::abs(height));
1075     finalWidth = static_cast<uint32_t>(std::abs(width));
1076     int32_t length = finalHeight * finalWidth * 4;
1077     JSRef<JSArrayBuffer> arrayBuffer = JSRef<JSArrayBuffer>::New(length);
1078     auto* buffer = static_cast<uint8_t*>(arrayBuffer->GetBuffer());
1079 
1080     BaseInfo baseInfo;
1081     baseInfo.canvasPattern = canvasPattern_;
1082     baseInfo.offscreenPattern = offscreenPattern_;
1083     baseInfo.isOffscreen = isOffscreen_;
1084 
1085     ImageSize imageSize;
1086     imageSize.left = left;
1087     imageSize.top = top;
1088     imageSize.width = width;
1089     imageSize.height = height;
1090     CanvasRendererModel::GetInstance()->GetImageDataModel(baseInfo, imageSize, buffer);
1091 
1092     JSRef<JSUint8ClampedArray> colorArray =
1093         JSRef<JSUint8ClampedArray>::New(arrayBuffer->GetLocalHandle(), 0, arrayBuffer->ByteLength());
1094 
1095     auto retObj = JSRef<JSObject>::New();
1096     retObj->SetProperty("width", finalWidth);
1097     retObj->SetProperty("height", finalHeight);
1098     retObj->SetPropertyObject("data", colorArray);
1099     info.SetReturnValue(retObj);
1100 }
1101 
JsGetPixelMap(const JSCallbackInfo & info)1102 void JSCanvasRenderer::JsGetPixelMap(const JSCallbackInfo& info)
1103 {
1104 #ifdef PIXEL_MAP_SUPPORTED
1105     // 0 Get input param
1106     double fLeft = 0.0;
1107     double fTop = 0.0;
1108     double fWidth = 0.0;
1109     double fHeight = 0.0;
1110     int32_t left = 0;
1111     int32_t top = 0;
1112     int32_t width = 0;
1113     int32_t height = 0;
1114 
1115     JSViewAbstract::ParseJsDouble(info[0], fLeft);
1116     JSViewAbstract::ParseJsDouble(info[1], fTop);
1117     JSViewAbstract::ParseJsDouble(info[2], fWidth);
1118     JSViewAbstract::ParseJsDouble(info[3], fHeight);
1119 
1120     fLeft = SystemProperties::Vp2Px(fLeft);
1121     fTop = SystemProperties::Vp2Px(fTop);
1122     fWidth = SystemProperties::Vp2Px(fWidth);
1123     fHeight = SystemProperties::Vp2Px(fHeight);
1124 
1125     left = fLeft;
1126     top = fTop;
1127     width = round(fWidth);
1128     height = round(fHeight);
1129 
1130     BaseInfo baseInfo;
1131     baseInfo.canvasPattern = canvasPattern_;
1132     baseInfo.offscreenPattern = offscreenPattern_;
1133     baseInfo.isOffscreen = isOffscreen_;
1134 
1135     ImageSize imageSize;
1136     imageSize.left = left;
1137     imageSize.top = top;
1138     imageSize.width = width;
1139     imageSize.height = height;
1140     auto pixelmap = CanvasRendererModel::GetInstance()->GetPixelMap(baseInfo, imageSize);
1141     CHECK_NULL_VOID(pixelmap);
1142 
1143     // 3 pixelmap to NapiValue
1144     auto engine = EngineHelper::GetCurrentEngine();
1145     if (!engine) {
1146         LOGE("JsGetPixelMap engine is null");
1147         return;
1148     }
1149     NativeEngine* nativeEngine = engine->GetNativeEngine();
1150     napi_env env = reinterpret_cast<napi_env>(nativeEngine);
1151     auto pixelmapSharedPtr = pixelmap->GetPixelMapSharedPtr();
1152     napi_value napiValue = OHOS::Media::PixelMapNapi::CreatePixelMap(env, pixelmapSharedPtr);
1153 
1154     // 4 NapiValue to JsValue
1155 #ifdef USE_ARK_ENGINE
1156     NativeValue* nativeValue = reinterpret_cast<NativeValue*>(napiValue);
1157     auto jsValue = JsConverter::ConvertNativeValueToJsVal(nativeValue);
1158     info.SetReturnValue(jsValue);
1159 #else
1160     napi_value temp = nullptr;
1161     napi_create_int32(env, 0, &temp);
1162     napi_set_named_property(env, napiValue, "index", temp);
1163 #endif
1164 #else
1165     LOGW("[Engine Log] The function 'getPixelMap' is not supported on the current platform.");
1166 #endif
1167 }
1168 
JsSetPixelMap(const JSCallbackInfo & info)1169 void JSCanvasRenderer::JsSetPixelMap(const JSCallbackInfo& info)
1170 {
1171     if (info.Length() != 1) {
1172         LOGE("The argv is wrong, it is supposed to have 1 argument");
1173         return;
1174     }
1175     CanvasImage image;
1176     RefPtr<PixelMap> pixelMap = nullptr;
1177     if (info[0]->IsObject()) {
1178 #if !defined(PREVIEW)
1179         pixelMap = CreatePixelMapFromNapiValue(info[0]);
1180 #endif
1181         if (!pixelMap) {
1182             LOGE("pixelMap is null");
1183             return;
1184         }
1185 
1186         BaseInfo baseInfo;
1187         baseInfo.canvasPattern = canvasPattern_;
1188         baseInfo.offscreenPattern = offscreenPattern_;
1189         baseInfo.isOffscreen = isOffscreen_;
1190 
1191         ImageInfo imageInfo;
1192         imageInfo.image = image;
1193         imageInfo.pixelMap = pixelMap;
1194 
1195         CanvasRendererModel::GetInstance()->DrawPixelMap(baseInfo, imageInfo);
1196     }
1197 }
1198 
JsDrawBitmapMesh(const JSCallbackInfo & info)1199 void JSCanvasRenderer::JsDrawBitmapMesh(const JSCallbackInfo& info)
1200 {
1201     RefPtr<AceType> OffscreenPattern;
1202 
1203     if (info.Length() != 4) {
1204         LOGE("info.Length is not right %{public}d", info.Length());
1205         return;
1206     }
1207 
1208     if (info[0]->IsObject()) {
1209         uint32_t id = 0;
1210         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
1211         JSRef<JSVal> jsId = obj->GetProperty("__id");
1212         JSViewAbstract::ParseJsInteger(jsId, id);
1213         OffscreenPattern = JSOffscreenRenderingContext::GetOffscreenPattern(id);
1214     } else {
1215         LOGE("info 0 is not object");
1216         return;
1217     }
1218 
1219     std::vector<double> mesh;
1220     double column;
1221     double row;
1222     if (!ParseJsDoubleArray(info[1], mesh)) {
1223         LOGE("info 1 is not double array");
1224         return;
1225     }
1226     if (!JSViewAbstract::ParseJsDouble(info[2], column)) {
1227         LOGE("info 2 is not double");
1228         return;
1229     }
1230     if (!JSViewAbstract::ParseJsDouble(info[3], row)) {
1231         LOGE("info 3 is not double");
1232         return;
1233     }
1234 
1235     BitmapMeshInfo bitmapMeshInfo;
1236     bitmapMeshInfo.pool = canvasPattern_;
1237     bitmapMeshInfo.offscreenPattern = OffscreenPattern;
1238     bitmapMeshInfo.mesh = mesh;
1239     bitmapMeshInfo.column = column;
1240     bitmapMeshInfo.row = row;
1241     CanvasRendererModel::GetInstance()->DrawBitmapMesh(bitmapMeshInfo);
1242 }
1243 
JsGetFilter(const JSCallbackInfo & info)1244 void JSCanvasRenderer::JsGetFilter(const JSCallbackInfo& info)
1245 {
1246     return;
1247 }
1248 
JsSetFilter(const JSCallbackInfo & info)1249 void JSCanvasRenderer::JsSetFilter(const JSCallbackInfo& info)
1250 {
1251     if (!info[0]->IsString() || info[0]->IsUndefined() || info[0]->IsNull()) {
1252         return;
1253     }
1254     std::string filterStr = "none";
1255     JSViewAbstract::ParseJsString(info[0], filterStr);
1256     if (filterStr == "") {
1257         LOGE("invalid filter string");
1258         return;
1259     }
1260 
1261     BaseInfo baseInfo;
1262     baseInfo.canvasPattern = canvasPattern_;
1263     baseInfo.offscreenPattern = offscreenPattern_;
1264     baseInfo.isOffscreen = isOffscreen_;
1265 
1266     CanvasRendererModel::GetInstance()->SetFilterParam(baseInfo, filterStr);
1267 }
1268 
JsGetDirection(const JSCallbackInfo & info)1269 void JSCanvasRenderer::JsGetDirection(const JSCallbackInfo& info)
1270 {
1271     return;
1272 }
1273 
JsSetDirection(const JSCallbackInfo & info)1274 void JSCanvasRenderer::JsSetDirection(const JSCallbackInfo& info)
1275 {
1276     if (!info[0]->IsString()) {
1277         return;
1278     }
1279     std::string directionStr;
1280     JSViewAbstract::ParseJsString(info[0], directionStr);
1281     auto direction = ConvertStrToTextDirection(directionStr);
1282 
1283     BaseInfo baseInfo;
1284     baseInfo.canvasPattern = canvasPattern_;
1285     baseInfo.offscreenPattern = offscreenPattern_;
1286     baseInfo.isOffscreen = isOffscreen_;
1287 
1288     CanvasRendererModel::GetInstance()->SetTextDirection(baseInfo, direction);
1289 }
1290 
JsGetJsonData(const JSCallbackInfo & info)1291 void JSCanvasRenderer::JsGetJsonData(const JSCallbackInfo& info)
1292 {
1293     std::string path = "";
1294     std::string jsonData = "";
1295 
1296     BaseInfo baseInfo;
1297     baseInfo.canvasPattern = canvasPattern_;
1298     baseInfo.offscreenPattern = offscreenPattern_;
1299     baseInfo.isOffscreen = isOffscreen_;
1300 
1301     if (info[0]->IsString()) {
1302         JSViewAbstract::ParseJsString(info[0], path);
1303         jsonData = CanvasRendererModel::GetInstance()->GetJsonData(baseInfo, path);
1304         auto returnValue = JSVal(ToJSValue(jsonData));
1305         auto returnPtr = JSRef<JSVal>::Make(returnValue);
1306         info.SetReturnValue(returnPtr);
1307     }
1308 }
1309 
JsToDataUrl(const JSCallbackInfo & info)1310 void JSCanvasRenderer::JsToDataUrl(const JSCallbackInfo& info)
1311 {
1312     std::string dataUrl = "";
1313     std::string result = "";
1314     double quality = DEFAULT_QUALITY;
1315     if (info[0]->IsString()) {
1316         JSViewAbstract::ParseJsString(info[0], dataUrl);
1317     }
1318     if (info.Length() > 1 && info[1]->IsNumber()) {
1319         JSViewAbstract::ParseJsDouble(info[1], quality);
1320     }
1321 
1322     BaseInfo baseInfo;
1323     baseInfo.canvasPattern = canvasPattern_;
1324     baseInfo.offscreenPattern = offscreenPattern_;
1325     baseInfo.isOffscreen = isOffscreen_;
1326 
1327     result = CanvasRendererModel::GetInstance()->ToDataURL(baseInfo, dataUrl, quality);
1328 
1329     auto returnValue = JSVal(ToJSValue(result));
1330     auto returnPtr = JSRef<JSVal>::Make(returnValue);
1331     info.SetReturnValue(returnPtr);
1332 }
1333 
JsSetLineCap(const JSCallbackInfo & info)1334 void JSCanvasRenderer::JsSetLineCap(const JSCallbackInfo& info)
1335 {
1336     if (info[0]->IsString()) {
1337         std::string capStr = "";
1338         JSViewAbstract::ParseJsString(info[0], capStr);
1339         static const LinearMapNode<LineCapStyle> lineCapTable[] = {
1340             { "butt", LineCapStyle::BUTT },
1341             { "round", LineCapStyle::ROUND },
1342             { "square", LineCapStyle::SQUARE },
1343         };
1344         auto lineCap = ConvertStrToEnum(capStr.c_str(), lineCapTable, ArraySize(lineCapTable), LineCapStyle::BUTT);
1345 
1346         BaseInfo baseInfo;
1347         baseInfo.canvasPattern = canvasPattern_;
1348         baseInfo.offscreenPattern = offscreenPattern_;
1349         baseInfo.isOffscreen = isOffscreen_;
1350 
1351         CanvasRendererModel::GetInstance()->SetLineCap(baseInfo, lineCap);
1352     }
1353 }
1354 
JsSetLineJoin(const JSCallbackInfo & info)1355 void JSCanvasRenderer::JsSetLineJoin(const JSCallbackInfo& info)
1356 {
1357     if (info[0]->IsString()) {
1358         std::string joinStr = "";
1359         JSViewAbstract::ParseJsString(info[0], joinStr);
1360         static const LinearMapNode<LineJoinStyle> lineJoinTable[3] = {
1361             { "bevel", LineJoinStyle::BEVEL },
1362             { "miter", LineJoinStyle::MITER },
1363             { "round", LineJoinStyle::ROUND },
1364         };
1365         auto lineJoin = ConvertStrToEnum(
1366             joinStr.c_str(), lineJoinTable, ArraySize(lineJoinTable), LineJoinStyle::MITER);
1367 
1368         BaseInfo baseInfo;
1369         baseInfo.canvasPattern = canvasPattern_;
1370         baseInfo.offscreenPattern = offscreenPattern_;
1371         baseInfo.isOffscreen = isOffscreen_;
1372 
1373         CanvasRendererModel::GetInstance()->SetLineJoin(baseInfo, lineJoin);
1374     }
1375 }
1376 
JsSetMiterLimit(const JSCallbackInfo & info)1377 void JSCanvasRenderer::JsSetMiterLimit(const JSCallbackInfo& info)
1378 {
1379     if (info[0]->IsNumber()) {
1380         double limit = 0.0;
1381         JSViewAbstract::ParseJsDouble(info[0], limit);
1382 
1383         BaseInfo baseInfo;
1384         baseInfo.canvasPattern = canvasPattern_;
1385         baseInfo.offscreenPattern = offscreenPattern_;
1386         baseInfo.isOffscreen = isOffscreen_;
1387 
1388         CanvasRendererModel::GetInstance()->SetMiterLimit(baseInfo, limit);
1389     }
1390 }
1391 
JsSetLineWidth(const JSCallbackInfo & info)1392 void JSCanvasRenderer::JsSetLineWidth(const JSCallbackInfo& info)
1393 {
1394     if (info[0]->IsNumber()) {
1395         double lineWidth = 0.0;
1396         JSViewAbstract::ParseJsDouble(info[0], lineWidth);
1397         lineWidth = SystemProperties::Vp2Px(lineWidth);
1398 
1399         BaseInfo baseInfo;
1400         baseInfo.canvasPattern = canvasPattern_;
1401         baseInfo.offscreenPattern = offscreenPattern_;
1402         baseInfo.isOffscreen = isOffscreen_;
1403 
1404         CanvasRendererModel::GetInstance()->SetLineWidth(baseInfo, lineWidth);
1405     }
1406 }
1407 
JsSetGlobalAlpha(const JSCallbackInfo & info)1408 void JSCanvasRenderer::JsSetGlobalAlpha(const JSCallbackInfo& info)
1409 {
1410     if (info[0]->IsNumber()) {
1411         double alpha = 0.0;
1412         JSViewAbstract::ParseJsDouble(info[0], alpha);
1413 
1414         BaseInfo baseInfo;
1415         baseInfo.canvasPattern = canvasPattern_;
1416         baseInfo.offscreenPattern = offscreenPattern_;
1417         baseInfo.isOffscreen = isOffscreen_;
1418 
1419         CanvasRendererModel::GetInstance()->SetGlobalAlpha(baseInfo, alpha);
1420     }
1421 }
1422 
JsSetGlobalCompositeOperation(const JSCallbackInfo & info)1423 void JSCanvasRenderer::JsSetGlobalCompositeOperation(const JSCallbackInfo& info)
1424 {
1425     if (info[0]->IsString()) {
1426         std::string compositeStr = "";
1427         JSViewAbstract::ParseJsString(info[0], compositeStr);
1428 
1429         static const LinearMapNode<CompositeOperation> compositeOperationTable[] = {
1430         { "copy", CompositeOperation::COPY },
1431         { "destination-atop", CompositeOperation::DESTINATION_ATOP },
1432         { "destination-in", CompositeOperation::DESTINATION_IN },
1433         { "destination-out", CompositeOperation::DESTINATION_OUT },
1434         { "destination-over", CompositeOperation::DESTINATION_OVER },
1435         { "lighter", CompositeOperation::LIGHTER },
1436         { "source-atop", CompositeOperation::SOURCE_ATOP },
1437 
1438         { "source-in", CompositeOperation::SOURCE_IN },
1439         { "source-out", CompositeOperation::SOURCE_OUT },
1440         { "source-over", CompositeOperation::SOURCE_OVER },
1441         { "xor", CompositeOperation::XOR },
1442         };
1443         auto type = ConvertStrToEnum(
1444             compositeStr.c_str(), compositeOperationTable,
1445             ArraySize(compositeOperationTable), CompositeOperation::SOURCE_OVER);
1446 
1447         BaseInfo baseInfo;
1448         baseInfo.canvasPattern = canvasPattern_;
1449         baseInfo.offscreenPattern = offscreenPattern_;
1450         baseInfo.isOffscreen = isOffscreen_;
1451 
1452         CanvasRendererModel::GetInstance()->SetCompositeType(baseInfo, type);
1453     }
1454 }
1455 
JsSetLineDashOffset(const JSCallbackInfo & info)1456 void JSCanvasRenderer::JsSetLineDashOffset(const JSCallbackInfo& info)
1457 {
1458     if (info[0]->IsNumber()) {
1459         double lineDashOffset = 0.0;
1460         JSViewAbstract::ParseJsDouble(info[0], lineDashOffset);
1461         lineDashOffset = SystemProperties::Vp2Px(lineDashOffset);
1462 
1463         BaseInfo baseInfo;
1464         baseInfo.canvasPattern = canvasPattern_;
1465         baseInfo.offscreenPattern = offscreenPattern_;
1466         baseInfo.isOffscreen = isOffscreen_;
1467 
1468         CanvasRendererModel::GetInstance()->SetLineDashOffset(baseInfo, lineDashOffset);
1469     }
1470 }
1471 
JsSetShadowBlur(const JSCallbackInfo & info)1472 void JSCanvasRenderer::JsSetShadowBlur(const JSCallbackInfo& info)
1473 {
1474     if (info[0]->IsNumber()) {
1475         double blur = 0.0;
1476         JSViewAbstract::ParseJsDouble(info[0], blur);
1477 
1478         BaseInfo baseInfo;
1479         baseInfo.canvasPattern = canvasPattern_;
1480         baseInfo.offscreenPattern = offscreenPattern_;
1481         baseInfo.isOffscreen = isOffscreen_;
1482 
1483         CanvasRendererModel::GetInstance()->SetShadowBlur(baseInfo, blur);
1484     }
1485 }
1486 
JsSetShadowColor(const JSCallbackInfo & info)1487 void JSCanvasRenderer::JsSetShadowColor(const JSCallbackInfo& info)
1488 {
1489     if (info[0]->IsString()) {
1490         std::string colorStr = "";
1491         JSViewAbstract::ParseJsString(info[0], colorStr);
1492         auto color = Color::FromString(colorStr);
1493 
1494         BaseInfo baseInfo;
1495         baseInfo.canvasPattern = canvasPattern_;
1496         baseInfo.offscreenPattern = offscreenPattern_;
1497         baseInfo.isOffscreen = isOffscreen_;
1498 
1499         CanvasRendererModel::GetInstance()->SetShadowColor(baseInfo, color);
1500     }
1501 }
1502 
JsSetShadowOffsetX(const JSCallbackInfo & info)1503 void JSCanvasRenderer::JsSetShadowOffsetX(const JSCallbackInfo& info)
1504 {
1505     if (info[0]->IsNumber()) {
1506         double offsetX = 0.0;
1507         JSViewAbstract::ParseJsDouble(info[0], offsetX);
1508         offsetX = SystemProperties::Vp2Px(offsetX);
1509 
1510         BaseInfo baseInfo;
1511         baseInfo.canvasPattern = canvasPattern_;
1512         baseInfo.offscreenPattern = offscreenPattern_;
1513         baseInfo.isOffscreen = isOffscreen_;
1514 
1515         CanvasRendererModel::GetInstance()->SetShadowOffsetX(baseInfo, offsetX);
1516     }
1517 }
1518 
JsSetShadowOffsetY(const JSCallbackInfo & info)1519 void JSCanvasRenderer::JsSetShadowOffsetY(const JSCallbackInfo& info)
1520 {
1521     if (info[0]->IsNumber()) {
1522         double offsetY = 0.0;
1523         JSViewAbstract::ParseJsDouble(info[0], offsetY);
1524         offsetY = SystemProperties::Vp2Px(offsetY);
1525 
1526         BaseInfo baseInfo;
1527         baseInfo.canvasPattern = canvasPattern_;
1528         baseInfo.offscreenPattern = offscreenPattern_;
1529         baseInfo.isOffscreen = isOffscreen_;
1530 
1531         CanvasRendererModel::GetInstance()->SetShadowOffsetY(baseInfo, offsetY);
1532     }
1533 }
1534 
JsSetImageSmoothingEnabled(const JSCallbackInfo & info)1535 void JSCanvasRenderer::JsSetImageSmoothingEnabled(const JSCallbackInfo& info)
1536 {
1537     if (info.Length() < 1) {
1538         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
1539         return;
1540     }
1541 
1542     bool enabled = false;
1543     if (JSViewAbstract::ParseJsBool(info[0], enabled)) {
1544         BaseInfo baseInfo;
1545         baseInfo.canvasPattern = canvasPattern_;
1546         baseInfo.offscreenPattern = offscreenPattern_;
1547         baseInfo.isOffscreen = isOffscreen_;
1548 
1549         CanvasRendererModel::GetInstance()->SetSmoothingEnabled(baseInfo, enabled);
1550     }
1551 }
1552 
JsSetImageSmoothingQuality(const JSCallbackInfo & info)1553 void JSCanvasRenderer::JsSetImageSmoothingQuality(const JSCallbackInfo& info)
1554 {
1555     if (info.Length() < 1) {
1556         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
1557         return;
1558     }
1559 
1560     std::string quality = "";
1561     if (JSViewAbstract::ParseJsString(info[0], quality)) {
1562         if (QUALITY_TYPE.find(quality) == QUALITY_TYPE.end()) {
1563             return;
1564         }
1565 
1566         BaseInfo baseInfo;
1567         baseInfo.canvasPattern = canvasPattern_;
1568         baseInfo.offscreenPattern = offscreenPattern_;
1569         baseInfo.isOffscreen = isOffscreen_;
1570 
1571         CanvasRendererModel::GetInstance()->SetSmoothingQuality(baseInfo, quality);
1572     }
1573 }
1574 
JsMoveTo(const JSCallbackInfo & info)1575 void JSCanvasRenderer::JsMoveTo(const JSCallbackInfo& info)
1576 {
1577     if (info.Length() < 1) {
1578         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1579         return;
1580     }
1581 
1582     if (info[0]->IsNumber() && info[1]->IsNumber()) {
1583         double x = 0.0;
1584         double y = 0.0;
1585         JSViewAbstract::ParseJsDouble(info[0], x);
1586         JSViewAbstract::ParseJsDouble(info[1], y);
1587         x = SystemProperties::Vp2Px(x);
1588         y = SystemProperties::Vp2Px(y);
1589 
1590         BaseInfo baseInfo;
1591         baseInfo.canvasPattern = canvasPattern_;
1592         baseInfo.offscreenPattern = offscreenPattern_;
1593         baseInfo.isOffscreen = isOffscreen_;
1594 
1595         CanvasRendererModel::GetInstance()->MoveTo(baseInfo, x, y);
1596     }
1597 }
1598 
JsLineTo(const JSCallbackInfo & info)1599 void JSCanvasRenderer::JsLineTo(const JSCallbackInfo& info)
1600 {
1601     if (info.Length() < 1) {
1602         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1603         return;
1604     }
1605 
1606     if (info[0]->IsNumber() && info[1]->IsNumber()) {
1607         double x = 0.0;
1608         double y = 0.0;
1609         JSViewAbstract::ParseJsDouble(info[0], x);
1610         JSViewAbstract::ParseJsDouble(info[1], y);
1611         x = SystemProperties::Vp2Px(x);
1612         y = SystemProperties::Vp2Px(y);
1613 
1614         BaseInfo baseInfo;
1615         baseInfo.canvasPattern = canvasPattern_;
1616         baseInfo.offscreenPattern = offscreenPattern_;
1617         baseInfo.isOffscreen = isOffscreen_;
1618 
1619         CanvasRendererModel::GetInstance()->LineTo(baseInfo, x, y);
1620     }
1621 }
1622 
JsBezierCurveTo(const JSCallbackInfo & info)1623 void JSCanvasRenderer::JsBezierCurveTo(const JSCallbackInfo& info)
1624 {
1625     if (info.Length() < 1) {
1626         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1627         return;
1628     }
1629 
1630     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()
1631         && info[4]->IsNumber() && info[5]->IsNumber()) {
1632         BezierCurveParam param;
1633         JSViewAbstract::ParseJsDouble(info[0], param.cp1x);
1634         JSViewAbstract::ParseJsDouble(info[1], param.cp1y);
1635         JSViewAbstract::ParseJsDouble(info[2], param.cp2x);
1636         JSViewAbstract::ParseJsDouble(info[3], param.cp2y);
1637         JSViewAbstract::ParseJsDouble(info[4], param.x);
1638         JSViewAbstract::ParseJsDouble(info[5], param.y);
1639         param.cp1x = SystemProperties::Vp2Px(param.cp1x);
1640         param.cp1y = SystemProperties::Vp2Px(param.cp1y);
1641         param.cp2x = SystemProperties::Vp2Px(param.cp2x);
1642         param.cp2y = SystemProperties::Vp2Px(param.cp2y);
1643         param.x = SystemProperties::Vp2Px(param.x);
1644         param.y = SystemProperties::Vp2Px(param.y);
1645 
1646         BaseInfo baseInfo;
1647         baseInfo.canvasPattern = canvasPattern_;
1648         baseInfo.offscreenPattern = offscreenPattern_;
1649         baseInfo.isOffscreen = isOffscreen_;
1650 
1651         CanvasRendererModel::GetInstance()->BezierCurveTo(baseInfo, param);
1652     }
1653 }
1654 
JsQuadraticCurveTo(const JSCallbackInfo & info)1655 void JSCanvasRenderer::JsQuadraticCurveTo(const JSCallbackInfo& info)
1656 {
1657     if (info.Length() < 1) {
1658         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1659         return;
1660     }
1661 
1662     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()) {
1663         QuadraticCurveParam param;
1664         JSViewAbstract::ParseJsDouble(info[0], param.cpx);
1665         JSViewAbstract::ParseJsDouble(info[1], param.cpy);
1666         JSViewAbstract::ParseJsDouble(info[2], param.x);
1667         JSViewAbstract::ParseJsDouble(info[3], param.y);
1668         param.cpx = SystemProperties::Vp2Px(param.cpx);
1669         param.cpy = SystemProperties::Vp2Px(param.cpy);
1670         param.x = SystemProperties::Vp2Px(param.x);
1671         param.y = SystemProperties::Vp2Px(param.y);
1672 
1673         BaseInfo baseInfo;
1674         baseInfo.canvasPattern = canvasPattern_;
1675         baseInfo.offscreenPattern = offscreenPattern_;
1676         baseInfo.isOffscreen = isOffscreen_;
1677 
1678         CanvasRendererModel::GetInstance()->QuadraticCurveTo(baseInfo, param);
1679     }
1680 }
1681 
JsArcTo(const JSCallbackInfo & info)1682 void JSCanvasRenderer::JsArcTo(const JSCallbackInfo& info)
1683 {
1684     if (info.Length() < 1) {
1685         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1686         return;
1687     }
1688 
1689     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()
1690         && info[4]->IsNumber()) {
1691         ArcToParam param;
1692         JSViewAbstract::ParseJsDouble(info[0], param.x1);
1693         JSViewAbstract::ParseJsDouble(info[1], param.y1);
1694         JSViewAbstract::ParseJsDouble(info[2], param.x2);
1695         JSViewAbstract::ParseJsDouble(info[3], param.y2);
1696         JSViewAbstract::ParseJsDouble(info[4], param.radius);
1697         param.x1 = SystemProperties::Vp2Px(param.x1);
1698         param.y1 = SystemProperties::Vp2Px(param.y1);
1699         param.x2 = SystemProperties::Vp2Px(param.x2);
1700         param.y2 = SystemProperties::Vp2Px(param.y2);
1701         param.radius = SystemProperties::Vp2Px(param.radius);
1702 
1703         BaseInfo baseInfo;
1704         baseInfo.canvasPattern = canvasPattern_;
1705         baseInfo.offscreenPattern = offscreenPattern_;
1706         baseInfo.isOffscreen = isOffscreen_;
1707 
1708         CanvasRendererModel::GetInstance()->ArcTo(baseInfo, param);
1709     }
1710 }
1711 
JsArc(const JSCallbackInfo & info)1712 void JSCanvasRenderer::JsArc(const JSCallbackInfo& info)
1713 {
1714     if (info.Length() < 1) {
1715         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1716         return;
1717     }
1718 
1719     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()
1720         && info[4]->IsNumber()) {
1721         ArcParam param;
1722         JSViewAbstract::ParseJsDouble(info[0], param.x);
1723         JSViewAbstract::ParseJsDouble(info[1], param.y);
1724         JSViewAbstract::ParseJsDouble(info[2], param.radius);
1725         JSViewAbstract::ParseJsDouble(info[3], param.startAngle);
1726         JSViewAbstract::ParseJsDouble(info[4], param.endAngle);
1727         param.x = SystemProperties::Vp2Px(param.x);
1728         param.y = SystemProperties::Vp2Px(param.y);
1729         param.radius = SystemProperties::Vp2Px(param.radius);
1730 
1731         if (info.Length() == 6) {
1732             JSViewAbstract::ParseJsBool(info[5], param.anticlockwise);
1733         }
1734 
1735         BaseInfo baseInfo;
1736         baseInfo.canvasPattern = canvasPattern_;
1737         baseInfo.offscreenPattern = offscreenPattern_;
1738         baseInfo.isOffscreen = isOffscreen_;
1739 
1740         CanvasRendererModel::GetInstance()->Arc(baseInfo, param);
1741     }
1742 }
1743 
JsEllipse(const JSCallbackInfo & info)1744 void JSCanvasRenderer::JsEllipse(const JSCallbackInfo& info)
1745 {
1746     if (info.Length() < 1) {
1747         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1748         return;
1749     }
1750 
1751     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()
1752         && info[4]->IsNumber() && info[5]->IsNumber() && info[6]->IsNumber()) {
1753         EllipseParam param;
1754         JSViewAbstract::ParseJsDouble(info[0], param.x);
1755         JSViewAbstract::ParseJsDouble(info[1], param.y);
1756         JSViewAbstract::ParseJsDouble(info[2], param.radiusX);
1757         JSViewAbstract::ParseJsDouble(info[3], param.radiusY);
1758         JSViewAbstract::ParseJsDouble(info[4], param.rotation);
1759         JSViewAbstract::ParseJsDouble(info[5], param.startAngle);
1760         JSViewAbstract::ParseJsDouble(info[6], param.endAngle);
1761         param.x = SystemProperties::Vp2Px(param.x);
1762         param.y = SystemProperties::Vp2Px(param.y);
1763         param.radiusX = SystemProperties::Vp2Px(param.radiusX);
1764         param.radiusY = SystemProperties::Vp2Px(param.radiusY);
1765 
1766         if (info.Length() == 8) {
1767             JSViewAbstract::ParseJsBool(info[7], param.anticlockwise);
1768         }
1769 
1770         BaseInfo baseInfo;
1771         baseInfo.canvasPattern = canvasPattern_;
1772         baseInfo.offscreenPattern = offscreenPattern_;
1773         baseInfo.isOffscreen = isOffscreen_;
1774 
1775         CanvasRendererModel::GetInstance()->Ellipse(baseInfo, param);
1776     }
1777 }
1778 
JsFill(const JSCallbackInfo & info)1779 void JSCanvasRenderer::JsFill(const JSCallbackInfo& info)
1780 {
1781     std::string ruleStr = "";
1782     if (info.Length() == 1 && info[0]->IsString()) {
1783         // fill(rule) uses fillRule specified by the application developers
1784         JSViewAbstract::ParseJsString(info[0], ruleStr);
1785     } else if (info.Length() == 2) {
1786         // fill(path, rule) uses fillRule specified by the application developers
1787         JSViewAbstract::ParseJsString(info[1], ruleStr);
1788     }
1789     auto fillRule = CanvasFillRule::NONZERO;
1790     if (ruleStr == "nonzero") {
1791         fillRule = CanvasFillRule::NONZERO;
1792     } else if (ruleStr == "evenodd") {
1793         fillRule = CanvasFillRule::EVENODD;
1794     }
1795 
1796     BaseInfo baseInfo;
1797     baseInfo.canvasPattern = canvasPattern_;
1798     baseInfo.offscreenPattern = offscreenPattern_;
1799     baseInfo.isOffscreen = isOffscreen_;
1800 
1801     if (info.Length() == 0 ||
1802         (info.Length() == 1 && info[0]->IsString())) {
1803         CanvasRendererModel::GetInstance()->SetFillRuleForPath(baseInfo, fillRule);
1804     } else if (info.Length() == 2 ||
1805         (info.Length() == 1 && info[0]->IsObject())) {
1806         JSPath2D* jsCanvasPath = JSRef<JSObject>::Cast(info[0])->Unwrap<JSPath2D>();
1807         if (jsCanvasPath == nullptr) {
1808             LOGE("The arg is wrong, it is supposed to have JSPath2D argument");
1809             return;
1810         }
1811         auto path = jsCanvasPath->GetCanvasPath2d();
1812 
1813         CanvasRendererModel::GetInstance()->SetFillRuleForPath2D(baseInfo, fillRule, path);
1814     }
1815 }
1816 
JsStroke(const JSCallbackInfo & info)1817 void JSCanvasRenderer::JsStroke(const JSCallbackInfo& info)
1818 {
1819     // stroke always uses non-zero fillRule
1820     auto fillRule = CanvasFillRule::NONZERO;
1821     BaseInfo baseInfo;
1822     baseInfo.canvasPattern = canvasPattern_;
1823     baseInfo.offscreenPattern = offscreenPattern_;
1824     baseInfo.isOffscreen = isOffscreen_;
1825 
1826     if (info.Length() == 1) {
1827         JSPath2D* jsCanvasPath = JSRef<JSObject>::Cast(info[0])->Unwrap<JSPath2D>();
1828         if (jsCanvasPath == nullptr) {
1829             LOGE("The arg is wrong, it is supposed to have JSPath2D argument");
1830             return;
1831         }
1832         auto path = jsCanvasPath->GetCanvasPath2d();
1833         CanvasRendererModel::GetInstance()->SetStrokeRuleForPath2D(baseInfo, fillRule, path);
1834         return;
1835     }
1836 
1837     CanvasRendererModel::GetInstance()->SetStrokeRuleForPath(baseInfo, fillRule);
1838 }
1839 
JsClip(const JSCallbackInfo & info)1840 void JSCanvasRenderer::JsClip(const JSCallbackInfo& info)
1841 {
1842     std::string ruleStr = "";
1843     if (info.Length() == 1 && info[0]->IsString()) {
1844         // clip(rule) uses fillRule specified by the application developers
1845         JSViewAbstract::ParseJsString(info[0], ruleStr);
1846     } else if (info.Length() == 2) {
1847         // clip(path, rule) uses fillRule specified by the application developers
1848         JSViewAbstract::ParseJsString(info[1], ruleStr);
1849     }
1850     auto fillRule = CanvasFillRule::NONZERO;
1851     if (ruleStr == "nonzero") {
1852         fillRule = CanvasFillRule::NONZERO;
1853     } else if (ruleStr == "evenodd") {
1854         fillRule = CanvasFillRule::EVENODD;
1855     }
1856 
1857     BaseInfo baseInfo;
1858     baseInfo.canvasPattern = canvasPattern_;
1859     baseInfo.offscreenPattern = offscreenPattern_;
1860     baseInfo.isOffscreen = isOffscreen_;
1861 
1862     if (info.Length() == 0 ||
1863         (info.Length() == 1 && info[0]->IsString())) {
1864         CanvasRendererModel::GetInstance()->SetClipRuleForPath(baseInfo, fillRule);
1865     } else if (info.Length() == 2 ||
1866         (info.Length() == 1 && info[0]->IsObject())) {
1867         JSPath2D* jsCanvasPath = JSRef<JSObject>::Cast(info[0])->Unwrap<JSPath2D>();
1868         if (jsCanvasPath == nullptr) {
1869             LOGE("The arg is wrong, it is supposed to have JSPath2D argument");
1870             return;
1871         }
1872         auto path = jsCanvasPath->GetCanvasPath2d();
1873         CanvasRendererModel::GetInstance()->SetClipRuleForPath2D(baseInfo, fillRule, path);
1874     }
1875 }
1876 
JsRect(const JSCallbackInfo & info)1877 void JSCanvasRenderer::JsRect(const JSCallbackInfo& info)
1878 {
1879     Rect rect = GetJsRectParam(info);
1880 
1881     BaseInfo baseInfo;
1882     baseInfo.canvasPattern = canvasPattern_;
1883     baseInfo.offscreenPattern = offscreenPattern_;
1884     baseInfo.isOffscreen = isOffscreen_;
1885 
1886     CanvasRendererModel::GetInstance()->AddRect(baseInfo, rect);
1887 }
1888 
JsBeginPath(const JSCallbackInfo & info)1889 void JSCanvasRenderer::JsBeginPath(const JSCallbackInfo& info)
1890 {
1891     if (info.Length() != 0) {
1892         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
1893         return;
1894     }
1895 
1896     BaseInfo baseInfo;
1897     baseInfo.canvasPattern = canvasPattern_;
1898     baseInfo.offscreenPattern = offscreenPattern_;
1899     baseInfo.isOffscreen = isOffscreen_;
1900 
1901     CanvasRendererModel::GetInstance()->BeginPath(baseInfo);
1902 }
1903 
JsClosePath(const JSCallbackInfo & info)1904 void JSCanvasRenderer::JsClosePath(const JSCallbackInfo& info)
1905 {
1906     if (info.Length() != 0) {
1907         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
1908         return;
1909     }
1910 
1911     BaseInfo baseInfo;
1912     baseInfo.canvasPattern = canvasPattern_;
1913     baseInfo.offscreenPattern = offscreenPattern_;
1914     baseInfo.isOffscreen = isOffscreen_;
1915 
1916     CanvasRendererModel::GetInstance()->ClosePath(baseInfo);
1917 }
1918 
JsRestore(const JSCallbackInfo & info)1919 void JSCanvasRenderer::JsRestore(const JSCallbackInfo& info)
1920 {
1921     if (info.Length() != 0) {
1922         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
1923         return;
1924     }
1925 
1926     BaseInfo baseInfo;
1927     baseInfo.canvasPattern = canvasPattern_;
1928     baseInfo.offscreenPattern = offscreenPattern_;
1929     baseInfo.isOffscreen = isOffscreen_;
1930 
1931     CanvasRendererModel::GetInstance()->Restore(baseInfo);
1932 }
1933 
JsSave(const JSCallbackInfo & info)1934 void JSCanvasRenderer::JsSave(const JSCallbackInfo& info)
1935 {
1936     if (info.Length() != 0) {
1937         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
1938         return;
1939     }
1940 
1941     BaseInfo baseInfo;
1942     baseInfo.canvasPattern = canvasPattern_;
1943     baseInfo.offscreenPattern = offscreenPattern_;
1944     baseInfo.isOffscreen = isOffscreen_;
1945 
1946     CanvasRendererModel::GetInstance()->CanvasRendererSave(baseInfo);
1947 }
1948 
JsRotate(const JSCallbackInfo & info)1949 void JSCanvasRenderer::JsRotate(const JSCallbackInfo& info)
1950 {
1951     if (info.Length() != 1) {
1952         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
1953         return;
1954     }
1955     double angle = 0.0;
1956     JSViewAbstract::ParseJsDouble(info[0], angle);
1957 
1958     BaseInfo baseInfo;
1959     baseInfo.canvasPattern = canvasPattern_;
1960     baseInfo.offscreenPattern = offscreenPattern_;
1961     baseInfo.isOffscreen = isOffscreen_;
1962 
1963     CanvasRendererModel::GetInstance()->CanvasRendererRotate(baseInfo, angle);
1964 }
1965 
JsScale(const JSCallbackInfo & info)1966 void JSCanvasRenderer::JsScale(const JSCallbackInfo& info)
1967 {
1968     if (info.Length() < 1) {
1969         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1970         return;
1971     }
1972 
1973     if (info[0]->IsNumber() && info[1]->IsNumber()) {
1974         double x = 0.0;
1975         double y = 0.0;
1976         JSViewAbstract::ParseJsDouble(info[0], x);
1977         JSViewAbstract::ParseJsDouble(info[1], y);
1978 
1979         BaseInfo baseInfo;
1980         baseInfo.canvasPattern = canvasPattern_;
1981         baseInfo.offscreenPattern = offscreenPattern_;
1982         baseInfo.isOffscreen = isOffscreen_;
1983 
1984         CanvasRendererModel::GetInstance()->CanvasRendererScale(baseInfo, x, y);
1985     }
1986 }
1987 
JsGetTransform(const JSCallbackInfo & info)1988 void JSCanvasRenderer::JsGetTransform(const JSCallbackInfo& info)
1989 {
1990     JSRef<JSObject> obj = JSClass<JSMatrix2d>::NewInstance();
1991     obj->SetProperty("__type", "Matrix2D");
1992     if (Container::IsCurrentUseNewPipeline()) {
1993         BaseInfo baseInfo;
1994         baseInfo.canvasPattern = canvasPattern_;
1995         baseInfo.offscreenPattern = offscreenPattern_;
1996         baseInfo.isOffscreen = isOffscreen_;
1997 
1998         TransformParam param = CanvasRendererModel::GetInstance()->GetTransform(baseInfo);
1999         auto matrix = Referenced::Claim(obj->Unwrap<JSMatrix2d>());
2000         CHECK_NULL_VOID(matrix);
2001         matrix->SetTransform(param);
2002     }
2003     info.SetReturnValue(obj);
2004 }
2005 
JsSetTransform(const JSCallbackInfo & info)2006 void JSCanvasRenderer::JsSetTransform(const JSCallbackInfo& info)
2007 {
2008     BaseInfo baseInfo;
2009     baseInfo.canvasPattern = canvasPattern_;
2010     baseInfo.offscreenPattern = offscreenPattern_;
2011     baseInfo.isOffscreen = isOffscreen_;
2012 
2013     if (info.Length() == 6) {
2014         if (!(info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()
2015             && info[4]->IsNumber() && info[5]->IsNumber())) {
2016             LOGE("The arg is not number.");
2017             return;
2018         }
2019         TransformParam param;
2020         JSViewAbstract::ParseJsDouble(info[0], param.scaleX);
2021         JSViewAbstract::ParseJsDouble(info[1], param.skewY);
2022         JSViewAbstract::ParseJsDouble(info[2], param.skewX);
2023         JSViewAbstract::ParseJsDouble(info[3], param.scaleY);
2024         JSViewAbstract::ParseJsDouble(info[4], param.translateX);
2025         JSViewAbstract::ParseJsDouble(info[5], param.translateY);
2026         param.translateX = SystemProperties::Vp2Px(param.translateX);
2027         param.translateY = SystemProperties::Vp2Px(param.translateY);
2028 
2029         CanvasRendererModel::GetInstance()->SetTransform(baseInfo, param, true);
2030         return;
2031     } else if (info.Length() == 1) {
2032         if (!info[0]->IsObject()) {
2033             LOGE("The arg is not Object or String.");
2034             return;
2035         }
2036         auto* jsMatrix2d = JSRef<JSObject>::Cast(info[0])->Unwrap<JSMatrix2d>();
2037         CHECK_NULL_VOID(jsMatrix2d);
2038         TransformParam param = jsMatrix2d->GetTransform();
2039         CanvasRendererModel::GetInstance()->SetTransform(baseInfo, param, false);
2040         LOGE("setTransform(Matrix2D) is not support.");
2041     } else {
2042         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
2043         return;
2044     }
2045 }
2046 
JsResetTransform(const JSCallbackInfo & info)2047 void JSCanvasRenderer::JsResetTransform(const JSCallbackInfo& info)
2048 {
2049     if (info.Length() != 0) {
2050         LOGE("The argv is wrong");
2051         return;
2052     }
2053 
2054     BaseInfo baseInfo;
2055     baseInfo.canvasPattern = canvasPattern_;
2056     baseInfo.offscreenPattern = offscreenPattern_;
2057     baseInfo.isOffscreen = isOffscreen_;
2058 
2059     CanvasRendererModel::GetInstance()->ResetTransform(baseInfo);
2060 }
2061 
JsTransform(const JSCallbackInfo & info)2062 void JSCanvasRenderer::JsTransform(const JSCallbackInfo& info)
2063 {
2064     if (info.Length() < 6) {
2065         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
2066         return;
2067     }
2068 
2069     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber() &&
2070         info[4]->IsNumber() && info[5]->IsNumber()) {
2071         TransformParam param;
2072         JSViewAbstract::ParseJsDouble(info[0], param.scaleX);
2073         JSViewAbstract::ParseJsDouble(info[1], param.skewX);
2074         JSViewAbstract::ParseJsDouble(info[2], param.skewY);
2075         JSViewAbstract::ParseJsDouble(info[3], param.scaleY);
2076         JSViewAbstract::ParseJsDouble(info[4], param.translateX);
2077         JSViewAbstract::ParseJsDouble(info[5], param.translateY);
2078         param.translateX = SystemProperties::Vp2Px(param.translateX);
2079         param.translateY = SystemProperties::Vp2Px(param.translateY);
2080 
2081         BaseInfo baseInfo;
2082         baseInfo.canvasPattern = canvasPattern_;
2083         baseInfo.offscreenPattern = offscreenPattern_;
2084         baseInfo.isOffscreen = isOffscreen_;
2085 
2086         CanvasRendererModel::GetInstance()->Transform(baseInfo, param);
2087     }
2088 }
2089 
JsTranslate(const JSCallbackInfo & info)2090 void JSCanvasRenderer::JsTranslate(const JSCallbackInfo& info)
2091 {
2092     if (info.Length() < 2) {
2093         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
2094         return;
2095     }
2096 
2097     if (info[0]->IsNumber() && info[1]->IsNumber()) {
2098         double x = 0.0;
2099         double y = 0.0;
2100         JSViewAbstract::ParseJsDouble(info[0], x);
2101         JSViewAbstract::ParseJsDouble(info[1], y);
2102         x = SystemProperties::Vp2Px(x);
2103         y = SystemProperties::Vp2Px(y);
2104 
2105         BaseInfo baseInfo;
2106         baseInfo.canvasPattern = canvasPattern_;
2107         baseInfo.offscreenPattern = offscreenPattern_;
2108         baseInfo.isOffscreen = isOffscreen_;
2109 
2110         CanvasRendererModel::GetInstance()->Translate(baseInfo, x, y);
2111     }
2112 }
2113 
JsSetLineDash(const JSCallbackInfo & info)2114 void JSCanvasRenderer::JsSetLineDash(const JSCallbackInfo& info)
2115 {
2116     std::vector<double> lineDash;
2117     ParseJsDoubleArray(info[0], lineDash);
2118     if (lineDash.size() % 2 != 0) {
2119         lineDash.insert(lineDash.end(), lineDash.begin(), lineDash.end());
2120     }
2121     if (!Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
2122         for (auto i = 0U; i < lineDash.size(); i++) {
2123             lineDash[i] = SystemProperties::Vp2Px(lineDash[i]);
2124         }
2125     }
2126 
2127     BaseInfo baseInfo;
2128     baseInfo.canvasPattern = canvasPattern_;
2129     baseInfo.offscreenPattern = offscreenPattern_;
2130     baseInfo.isOffscreen = isOffscreen_;
2131 
2132     CanvasRendererModel::GetInstance()->SetLineDash(baseInfo, lineDash);
2133 }
2134 
GetPattern(unsigned int id)2135 Pattern JSCanvasRenderer::GetPattern(unsigned int id)
2136 {
2137     if (id < 0 || id >= pattern_.size()) {
2138         return Pattern();
2139     }
2140     return *(pattern_[id].get());
2141 }
2142 
GetPatternNG(int32_t id)2143 std::weak_ptr<Ace::Pattern> JSCanvasRenderer::GetPatternNG(int32_t id)
2144 {
2145     if (id < 0) {
2146         return std::shared_ptr<Pattern>();
2147     }
2148     return pattern_[id];
2149 }
2150 
GetPatternPtr(int32_t id)2151 std::shared_ptr<Pattern> JSCanvasRenderer::GetPatternPtr(int32_t id)
2152 {
2153     if (id < 0 || id >= static_cast<int32_t>(pattern_.size())) {
2154         return std::shared_ptr<Pattern>();
2155     }
2156     return pattern_[id];
2157 }
2158 
SetTransform(unsigned int id,const TransformParam & transform)2159 void JSCanvasRenderer::SetTransform(unsigned int id, const TransformParam& transform)
2160 {
2161     if (id >= 0 && id <= patternCount_) {
2162         pattern_[id]->SetScaleX(transform.scaleX);
2163         pattern_[id]->SetScaleY(transform.scaleY);
2164         pattern_[id]->SetSkewX(transform.skewX);
2165         pattern_[id]->SetSkewY(transform.skewY);
2166         pattern_[id]->SetTranslateX(transform.translateX);
2167         pattern_[id]->SetTranslateY(transform.translateY);
2168     }
2169 }
2170 
JsSetTextAlign(const JSCallbackInfo & info)2171 void JSCanvasRenderer::JsSetTextAlign(const JSCallbackInfo& info)
2172 {
2173     if (info.Length() < 1) {
2174         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
2175         return;
2176     }
2177 
2178     BaseInfo baseInfo;
2179     baseInfo.canvasPattern = canvasPattern_;
2180     baseInfo.offscreenPattern = offscreenPattern_;
2181     baseInfo.isOffscreen = isOffscreen_;
2182 
2183     std::string value = "";
2184     if (info[0]->IsString()) {
2185         JSViewAbstract::ParseJsString(info[0], value);
2186         auto align = ConvertStrToTextAlign(value);
2187         paintState_.SetTextAlign(align);
2188         CanvasRendererModel::GetInstance()->SetTextAlign(baseInfo, align);
2189     }
2190 }
2191 
JsSetTextBaseline(const JSCallbackInfo & info)2192 void JSCanvasRenderer::JsSetTextBaseline(const JSCallbackInfo& info)
2193 {
2194     if (info.Length() < 1) {
2195         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
2196         return;
2197     }
2198 
2199     std::string textBaseline;
2200     if (info[0]->IsString()) {
2201         JSViewAbstract::ParseJsString(info[0], textBaseline);
2202         auto baseline = ConvertStrToEnum(
2203             textBaseline.c_str(), BASELINE_TABLE, ArraySize(BASELINE_TABLE), TextBaseline::ALPHABETIC);
2204         style_.SetTextBaseline(baseline);
2205 
2206         BaseInfo baseInfo;
2207         baseInfo.canvasPattern = canvasPattern_;
2208         baseInfo.offscreenPattern = offscreenPattern_;
2209         baseInfo.isOffscreen = isOffscreen_;
2210 
2211         CanvasRendererModel::GetInstance()->SetTextBaseline(baseInfo, baseline);
2212     }
2213 }
2214 
JsMeasureText(const JSCallbackInfo & info)2215 void JSCanvasRenderer::JsMeasureText(const JSCallbackInfo& info)
2216 {
2217     std::string text = "";
2218     paintState_.SetTextStyle(style_);
2219     double width = 0.0;
2220     double height = 0.0;
2221     double actualBoundingBoxLeft = 0.0;
2222     double actualBoundingBoxRight = 0.0;
2223     double actualBoundingBoxAscent = 0.0;
2224     double actualBoundingBoxDescent = 0.0;
2225     double hangingBaseline = 0.0;
2226     double alphabeticBaseline = 0.0;
2227     double ideographicBaseline = 0.0;
2228     double emHeightAscent = 0.0;
2229     double emHeightDescent = 0.0;
2230     double fontBoundingBoxAscent = 0.0;
2231     double fontBoundingBoxDescent = 0.0;
2232     if (info[0]->IsString()) {
2233         JSViewAbstract::ParseJsString(info[0], text);
2234 
2235         BaseInfo baseInfo;
2236         baseInfo.canvasPattern = canvasPattern_;
2237         baseInfo.offscreenPattern = offscreenPattern_;
2238         baseInfo.isOffscreen = isOffscreen_;
2239         baseInfo.paintState = paintState_;
2240 
2241         width = CanvasRendererModel::GetInstance()->GetMeasureTextWidth(baseInfo, text);
2242         height = CanvasRendererModel::GetInstance()->GetMeasureTextHeight(baseInfo, text);
2243 
2244         auto retObj = JSRef<JSObject>::New();
2245         retObj->SetProperty("width", SystemProperties::Px2Vp(width));
2246         retObj->SetProperty("height", SystemProperties::Px2Vp(height));
2247         retObj->SetProperty("actualBoundingBoxLeft", SystemProperties::Px2Vp(actualBoundingBoxLeft));
2248         retObj->SetProperty("actualBoundingBoxRight", SystemProperties::Px2Vp(actualBoundingBoxRight));
2249         retObj->SetProperty("actualBoundingBoxAscent", SystemProperties::Px2Vp(actualBoundingBoxAscent));
2250         retObj->SetProperty("actualBoundingBoxDescent", SystemProperties::Px2Vp(actualBoundingBoxDescent));
2251         retObj->SetProperty("hangingBaseline", SystemProperties::Px2Vp(hangingBaseline));
2252         retObj->SetProperty("alphabeticBaseline", SystemProperties::Px2Vp(alphabeticBaseline));
2253         retObj->SetProperty("ideographicBaseline", SystemProperties::Px2Vp(ideographicBaseline));
2254         retObj->SetProperty("emHeightAscent", SystemProperties::Px2Vp(emHeightAscent));
2255         retObj->SetProperty("emHeightDescent", SystemProperties::Px2Vp(emHeightDescent));
2256         retObj->SetProperty("fontBoundingBoxAscent", SystemProperties::Px2Vp(fontBoundingBoxAscent));
2257         retObj->SetProperty("fontBoundingBoxDescent", SystemProperties::Px2Vp(fontBoundingBoxDescent));
2258         info.SetReturnValue(retObj);
2259     }
2260 }
2261 
JsFillRect(const JSCallbackInfo & info)2262 void JSCanvasRenderer::JsFillRect(const JSCallbackInfo& info)
2263 {
2264     if (info.Length() < 4) {
2265         LOGE("The arg is wrong, it is supposed to have at least 4 argument");
2266         return;
2267     }
2268 
2269     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()) {
2270         double x = 0.0;
2271         double y = 0.0;
2272         double width = 0.0;
2273         double height = 0.0;
2274         JSViewAbstract::ParseJsDouble(info[0], x);
2275         JSViewAbstract::ParseJsDouble(info[1], y);
2276         JSViewAbstract::ParseJsDouble(info[2], width);
2277         JSViewAbstract::ParseJsDouble(info[3], height);
2278         x = SystemProperties::Vp2Px(x);
2279         y = SystemProperties::Vp2Px(y);
2280         width = SystemProperties::Vp2Px(width);
2281         height = SystemProperties::Vp2Px(height);
2282 
2283         Rect rect = Rect(x, y, width, height);
2284 
2285         BaseInfo baseInfo;
2286         baseInfo.canvasPattern = canvasPattern_;
2287         baseInfo.offscreenPattern = offscreenPattern_;
2288         baseInfo.isOffscreen = isOffscreen_;
2289 
2290         CanvasRendererModel::GetInstance()->FillRect(baseInfo, rect);
2291     }
2292 }
2293 
JsStrokeRect(const JSCallbackInfo & info)2294 void JSCanvasRenderer::JsStrokeRect(const JSCallbackInfo& info)
2295 {
2296     if (info.Length() < 4) {
2297         LOGE("The arg is wrong, it is supposed to have at least 4 argument");
2298         return;
2299     }
2300 
2301     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()) {
2302         double x = 0.0;
2303         double y = 0.0;
2304         double width = 0.0;
2305         double height = 0.0;
2306         JSViewAbstract::ParseJsDouble(info[0], x);
2307         JSViewAbstract::ParseJsDouble(info[1], y);
2308         JSViewAbstract::ParseJsDouble(info[2], width);
2309         JSViewAbstract::ParseJsDouble(info[3], height);
2310         x = SystemProperties::Vp2Px(x);
2311         y = SystemProperties::Vp2Px(y);
2312         width = SystemProperties::Vp2Px(width);
2313         height = SystemProperties::Vp2Px(height);
2314 
2315         Rect rect = Rect(x, y, width, height);
2316 
2317         BaseInfo baseInfo;
2318         baseInfo.canvasPattern = canvasPattern_;
2319         baseInfo.offscreenPattern = offscreenPattern_;
2320         baseInfo.isOffscreen = isOffscreen_;
2321 
2322         CanvasRendererModel::GetInstance()->StrokeRect(baseInfo, rect);
2323     }
2324 }
2325 
JsClearRect(const JSCallbackInfo & info)2326 void JSCanvasRenderer::JsClearRect(const JSCallbackInfo& info)
2327 {
2328     if (info.Length() < 4) {
2329         LOGE("The arg is wrong, it is supposed to have at least 4 argument");
2330         return;
2331     }
2332 
2333     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()) {
2334         double x = 0.0;
2335         double y = 0.0;
2336         double width = 0.0;
2337         double height = 0.0;
2338         JSViewAbstract::ParseJsDouble(info[0], x);
2339         JSViewAbstract::ParseJsDouble(info[1], y);
2340         JSViewAbstract::ParseJsDouble(info[2], width);
2341         JSViewAbstract::ParseJsDouble(info[3], height);
2342         x = SystemProperties::Vp2Px(x);
2343         y = SystemProperties::Vp2Px(y);
2344         width = SystemProperties::Vp2Px(width);
2345         height = SystemProperties::Vp2Px(height);
2346 
2347         Rect rect = Rect(x, y, width, height);
2348 
2349         BaseInfo baseInfo;
2350         baseInfo.canvasPattern = canvasPattern_;
2351         baseInfo.offscreenPattern = offscreenPattern_;
2352         baseInfo.isOffscreen = isOffscreen_;
2353 
2354         CanvasRendererModel::GetInstance()->ClearRect(baseInfo, rect);
2355     }
2356 }
2357 
SetCanvasPattern(const RefPtr<AceType> & canvas)2358 void JSCanvasRenderer::SetCanvasPattern(const RefPtr<AceType>& canvas)
2359 {
2360     canvasPattern_ = canvas;
2361     isOffscreen_ = false;
2362     BaseInfo baseInfo;
2363     baseInfo.canvasPattern = canvasPattern_;
2364     baseInfo.offscreenPattern = offscreenPattern_;
2365     baseInfo.isOffscreen = isOffscreen_;
2366     CanvasRendererModel::GetInstance()->SetShadowColor(baseInfo, Color::TRANSPARENT);
2367 }
2368 
SetOffscreenPattern(const RefPtr<AceType> & offscreenCanvas)2369 void JSCanvasRenderer::SetOffscreenPattern(const RefPtr<AceType>& offscreenCanvas)
2370 {
2371     offscreenPattern_ = offscreenCanvas;
2372     isOffscreen_ = true;
2373     BaseInfo baseInfo;
2374     baseInfo.canvasPattern = canvasPattern_;
2375     baseInfo.offscreenPattern = offscreenPattern_;
2376     baseInfo.isOffscreen = isOffscreen_;
2377     CanvasRendererModel::GetInstance()->SetShadowColor(baseInfo, Color::TRANSPARENT);
2378 }
2379 } // namespace OHOS::Ace::Framework