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