• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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_utils.h"
22 
23 #ifdef PIXEL_MAP_SUPPORTED
24 #include "pixel_map.h"
25 #include "pixel_map_napi.h"
26 #endif
27 namespace OHOS::Ace::Framework {
28 std::unordered_map<int32_t, Pattern> JSCanvasRenderer::pattern_;
29 int32_t JSCanvasRenderer::patternCount_ = 0;
30 namespace {
31 
32 const std::set<std::string> FONT_WEIGHTS = {
33     "normal", "bold", "lighter", "bolder",
34     "100", "200", "300", "400", "500", "600", "700", "800", "900"
35 };
36 const std::set<std::string> FONT_STYLES = { "italic", "oblique", "normal" };
37 const std::set<std::string> FONT_FAMILIES = { "sans-serif", "serif", "monospace" };
38 const std::set<std::string> QUALITY_TYPE = { "low", "medium", "high" }; // Defaulte value is low.
39 constexpr double DEFAULT_QUALITY = 0.92;
40 template<typename T>
ConvertStrToEnum(const char * key,const LinearMapNode<T> * map,size_t length,T defaultValue)41 inline T ConvertStrToEnum(const char* key, const LinearMapNode<T>* map, size_t length, T defaultValue)
42 {
43     int64_t index = BinarySearchFindIndex(map, length, key);
44     return index != -1 ? map[index].value : defaultValue;
45 }
46 
GetJsRectParam(const JSCallbackInfo & info)47 inline Rect GetJsRectParam(const JSCallbackInfo& info)
48 {
49     // 4 parameters: rect(x, y, width, height)
50     if (info.Length() != 4) {
51         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
52         return Rect();
53     }
54     double x = 0.0;
55     double y = 0.0;
56     double width = 0.0;
57     double height = 0.0;
58     JSViewAbstract::ParseJsDouble(info[0], x);
59     JSViewAbstract::ParseJsDouble(info[1], y);
60     JSViewAbstract::ParseJsDouble(info[2], width);
61     JSViewAbstract::ParseJsDouble(info[3], height);
62     x = SystemProperties::Vp2Px(x);
63     y = SystemProperties::Vp2Px(y);
64     width = SystemProperties::Vp2Px(width);
65     height = SystemProperties::Vp2Px(height);
66 
67     Rect rect = Rect(x, y, width, height);
68     return rect;
69 }
70 
ParseJsDoubleArray(const JSRef<JSVal> & jsValue,std::vector<double> & result)71 inline bool ParseJsDoubleArray(const JSRef<JSVal>& jsValue, std::vector<double>& result)
72 {
73     if (!jsValue->IsArray() && !jsValue->IsObject()) {
74         LOGE("arg is not array or Object.");
75         return false;
76     }
77 
78     if (jsValue->IsArray()) {
79         JSRef<JSArray> array = JSRef<JSArray>::Cast(jsValue);
80         for (size_t i = 0; i < array->Length(); i++) {
81             JSRef<JSVal> value = array->GetValueAt(i);
82             if (value->IsNumber()) {
83                 result.emplace_back(value->ToNumber<double>());
84             } else if (value->IsObject()) {
85                 double singleResInt;
86                 if (JSViewAbstract::ParseJsDouble(value, singleResInt)) {
87                     result.emplace_back(singleResInt);
88                 } else {
89                     return false;
90                 }
91             } else {
92                 return false;
93             }
94         }
95         return true;
96     }
97     return false;
98 }
99 
ParseJsInt(const JSRef<JSVal> & jsValue,int32_t & result)100 inline bool ParseJsInt(const JSRef<JSVal>& jsValue, int32_t& result)
101 {
102     if (!jsValue->IsNumber() && !jsValue->IsObject()) {
103         LOGE("arg is not number or Object.");
104         return false;
105     }
106 
107     if (jsValue->IsNumber()) {
108         LOGD("jsValue->IsNumber()");
109         result = jsValue->ToNumber<int32_t>();
110         return true;
111     }
112 
113     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
114     JSRef<JSVal> type = jsObj->GetProperty("type");
115     if (!type->IsNumber()) {
116         LOGW("type is not number");
117         return false;
118     }
119 
120     JSRef<JSVal> resId = jsObj->GetProperty("id");
121     if (!resId->IsNumber()) {
122         LOGW("resId is not number");
123         return false;
124     }
125     return false;
126 }
127 
128 const LinearMapNode<TextBaseline> BASELINE_TABLE[] = {
129     { "alphabetic", TextBaseline::ALPHABETIC },
130     { "bottom", TextBaseline::BOTTOM },
131     { "hanging", TextBaseline::HANGING },
132     { "ideographic", TextBaseline::IDEOGRAPHIC },
133     { "middle", TextBaseline::MIDDLE },
134     { "top", TextBaseline::TOP },
135 };
136 
137 } // namespace
138 
JSCanvasRenderer()139 JSCanvasRenderer::JSCanvasRenderer()
140 {
141 }
142 
JsCreateLinearGradient(const JSCallbackInfo & info)143 void JSCanvasRenderer::JsCreateLinearGradient(const JSCallbackInfo& info)
144 {
145     JSRef<JSObject> pasteObj = JSClass<JSCanvasGradient>::NewInstance();
146     pasteObj->SetProperty("__type", "gradient");
147 
148     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber()
149         && info[3]->IsNumber()) {
150         double x0 = 0.0;
151         double y0 = 0.0;
152         double x1 = 0.0;
153         double y1 = 0.0;
154         JSViewAbstract::ParseJsDouble(info[0], x0);
155         JSViewAbstract::ParseJsDouble(info[1], y0);
156         JSViewAbstract::ParseJsDouble(info[2], x1);
157         JSViewAbstract::ParseJsDouble(info[3], y1);
158         x0 = SystemProperties::Vp2Px(x0);
159         y0 = SystemProperties::Vp2Px(y0);
160         x1 = SystemProperties::Vp2Px(x1);
161         y1 = SystemProperties::Vp2Px(y1);
162         Offset beginOffset = Offset(x0, y0);
163         Offset endOffset = Offset(x1, y1);
164 
165         Gradient* gradient = new Gradient();
166         gradient->SetType(GradientType::LINEAR);
167         gradient->SetBeginOffset(beginOffset);
168         gradient->SetEndOffset(endOffset);
169 
170         auto pasteData = Referenced::Claim(pasteObj->Unwrap<JSCanvasGradient>());
171         pasteData->SetGradient(gradient);
172         info.SetReturnValue(pasteObj);
173     }
174 }
175 
JsCreateRadialGradient(const JSCallbackInfo & info)176 void JSCanvasRenderer::JsCreateRadialGradient(const JSCallbackInfo& info)
177 {
178     JSRef<JSObject> pasteObj = JSClass<JSCanvasGradient>::NewInstance();
179     pasteObj->SetProperty("__type", "gradient");
180 
181     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber()
182         && info[3]->IsNumber()  && info[4]->IsNumber() && info[5]->IsNumber()) {
183         double startX = 0.0;
184         double startY = 0.0;
185         double startRadial = 0.0;
186         double endX = 0.0;
187         double endY = 0.0;
188         double endRadial = 0.0;
189         JSViewAbstract::ParseJsDouble(info[0], startX);
190         JSViewAbstract::ParseJsDouble(info[1], startY);
191         JSViewAbstract::ParseJsDouble(info[2], startRadial);
192         JSViewAbstract::ParseJsDouble(info[3], endX);
193         JSViewAbstract::ParseJsDouble(info[4], endY);
194         JSViewAbstract::ParseJsDouble(info[5], endRadial);
195         startX = SystemProperties::Vp2Px(startX);
196         startY = SystemProperties::Vp2Px(startY);
197         startRadial = SystemProperties::Vp2Px(startRadial);
198         endX = SystemProperties::Vp2Px(endX);
199         endY = SystemProperties::Vp2Px(endY);
200         endRadial = SystemProperties::Vp2Px(endRadial);
201         Offset innerCenter = Offset(startX, startY);
202         Offset outerCenter = Offset(endX, endY);
203 
204         Gradient* gradient = new Gradient();
205         gradient->SetType(GradientType::RADIAL);
206         gradient->SetBeginOffset(innerCenter);
207         gradient->SetEndOffset(outerCenter);
208         gradient->SetInnerRadius(startRadial);
209         gradient->SetOuterRadius(endRadial);
210 
211         auto pasteData = Referenced::Claim(pasteObj->Unwrap<JSCanvasGradient>());
212         pasteData->SetGradient(gradient);
213         info.SetReturnValue(pasteObj);
214     }
215 }
216 
JsFillText(const JSCallbackInfo & info)217 void JSCanvasRenderer::JsFillText(const JSCallbackInfo& info)
218 {
219     if (info.Length() < 1) {
220         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
221         return;
222     }
223 
224     if (info[0]->IsString() && info[1]->IsNumber() && info[2]->IsNumber()) {
225         double x = 0.0;
226         double y = 0.0;
227         std::string text = "";
228         JSViewAbstract::ParseJsString(info[0], text);
229         JSViewAbstract::ParseJsDouble(info[1], x);
230         JSViewAbstract::ParseJsDouble(info[2], y);
231         x = SystemProperties::Vp2Px(x);
232         y = SystemProperties::Vp2Px(y);
233 
234         if (isOffscreen_) {
235             offscreenCanvas_->FillText(text, x, y, paintState_);
236         } else {
237             pool_->FillText(text, Offset(x, y));
238         }
239     }
240 }
241 
JsStrokeText(const JSCallbackInfo & info)242 void JSCanvasRenderer::JsStrokeText(const JSCallbackInfo& info)
243 {
244     if (info.Length() < 1) {
245         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
246         return;
247     }
248 
249     if (info[0]->IsString() && info[1]->IsNumber() && info[2]->IsNumber()) {
250         double x = 0.0;
251         double y = 0.0;
252         std::string text = "";
253         JSViewAbstract::ParseJsString(info[0], text);
254         JSViewAbstract::ParseJsDouble(info[1], x);
255         JSViewAbstract::ParseJsDouble(info[2], y);
256         x = SystemProperties::Vp2Px(x);
257         y = SystemProperties::Vp2Px(y);
258 
259         if (isOffscreen_) {
260             offscreenCanvas_->StrokeText(text, x, y, paintState_);
261         } else {
262             pool_->StrokeText(text, Offset(x, y));
263         }
264     }
265 }
266 
SetAntiAlias()267 void JSCanvasRenderer::SetAntiAlias()
268 {
269     if (isOffscreen_) {
270         offscreenCanvas_->SetAntiAlias(anti_);
271     } else {
272         pool_->SetAntiAlias(anti_);
273     }
274 }
275 
JsSetFont(const JSCallbackInfo & info)276 void JSCanvasRenderer::JsSetFont(const JSCallbackInfo& info)
277 {
278     if (info.Length() < 1) {
279         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
280         return;
281     }
282     std::string fontStr = "";
283     JSViewAbstract::ParseJsString(info[0], fontStr);
284 
285     std::vector<std::string> fontProps;
286     StringUtils::StringSpliter(fontStr.c_str(), ' ', fontProps);
287     bool updateFontStyle = false;
288     for (const auto& fontProp : fontProps) {
289         if (FONT_WEIGHTS.find(fontProp) != FONT_WEIGHTS.end()) {
290             auto weight = ConvertStrToFontWeight(fontProp);
291             if (isOffscreen_) {
292                 offscreenCanvas_->SetFontWeight(weight);
293             } else {
294                 pool_->UpdateFontWeight(weight);
295             }
296 
297             style_.SetFontWeight(weight);
298         } else if (FONT_STYLES.find(fontProp) != FONT_STYLES.end()) {
299             updateFontStyle = true;
300             auto fontStyle = ConvertStrToFontStyle(fontProp);
301             if (isOffscreen_) {
302                 offscreenCanvas_->SetFontStyle(fontStyle);
303             } else {
304                 pool_->UpdateFontStyle(fontStyle);
305             }
306             style_.SetFontStyle(fontStyle);
307         } else if (FONT_FAMILIES.find(fontProp) != FONT_FAMILIES.end()) {
308             auto families = ConvertStrToFontFamilies(fontProp);
309             if (isOffscreen_) {
310                 offscreenCanvas_->SetFontFamilies(families);
311             } else {
312                 pool_->UpdateFontFamilies(families);
313             }
314             style_.SetFontFamilies(families);
315         } else if (fontProp.find("px") != std::string::npos) {
316             std::string fontSize = fontProp.substr(0, fontProp.size() - 2);
317             auto size = Dimension(StringToDouble(fontProp));
318             if (isOffscreen_) {
319                 offscreenCanvas_->SetFontSize(size);
320             } else {
321                 pool_->UpdateFontSize(size);
322             }
323             style_.SetFontSize(size);
324         } else {
325             LOGW("parse text error");
326         }
327     }
328     if (!updateFontStyle) {
329         if (isOffscreen_) {
330             offscreenCanvas_->SetFontStyle(FontStyle::NORMAL);
331         } else {
332             pool_->UpdateFontStyle(FontStyle::NORMAL);
333         }
334     }
335 }
336 
JsGetFont(const JSCallbackInfo & info)337 void JSCanvasRenderer::JsGetFont(const JSCallbackInfo& info)
338 {
339     return;
340 }
341 
JsGetFillStyle(const JSCallbackInfo & info)342 void JSCanvasRenderer::JsGetFillStyle(const JSCallbackInfo& info)
343 {
344     return;
345 }
346 
JsGetStrokeStyle(const JSCallbackInfo & info)347 void JSCanvasRenderer::JsGetStrokeStyle(const JSCallbackInfo& info)
348 {
349     return;
350 }
351 
JsGetLineCap(const JSCallbackInfo & info)352 void JSCanvasRenderer::JsGetLineCap(const JSCallbackInfo& info)
353 {
354     return;
355 }
356 
JsGetLineJoin(const JSCallbackInfo & info)357 void JSCanvasRenderer::JsGetLineJoin(const JSCallbackInfo& info)
358 {
359     return;
360 }
361 
JsGetMiterLimit(const JSCallbackInfo & info)362 void JSCanvasRenderer::JsGetMiterLimit(const JSCallbackInfo& info)
363 {
364     return;
365 }
366 
JsGetLineWidth(const JSCallbackInfo & info)367 void JSCanvasRenderer::JsGetLineWidth(const JSCallbackInfo& info)
368 {
369     return;
370 }
371 
JsGetTextAlign(const JSCallbackInfo & info)372 void JSCanvasRenderer::JsGetTextAlign(const JSCallbackInfo& info)
373 {
374     return;
375 }
376 
JsGetTextBaseline(const JSCallbackInfo & info)377 void JSCanvasRenderer::JsGetTextBaseline(const JSCallbackInfo& info)
378 {
379     return;
380 }
381 
JsGetGlobalAlpha(const JSCallbackInfo & info)382 void JSCanvasRenderer::JsGetGlobalAlpha(const JSCallbackInfo& info)
383 {
384     return;
385 }
386 
JsGetGlobalCompositeOperation(const JSCallbackInfo & info)387 void JSCanvasRenderer::JsGetGlobalCompositeOperation(const JSCallbackInfo& info)
388 {
389     return;
390 }
391 
JsGetLineDashOffset(const JSCallbackInfo & info)392 void JSCanvasRenderer::JsGetLineDashOffset(const JSCallbackInfo& info)
393 {
394     return;
395 }
396 
JsGetShadowBlur(const JSCallbackInfo & info)397 void JSCanvasRenderer::JsGetShadowBlur(const JSCallbackInfo& info)
398 {
399     return;
400 }
401 
JsGetShadowColor(const JSCallbackInfo & info)402 void JSCanvasRenderer::JsGetShadowColor(const JSCallbackInfo& info)
403 {
404     return;
405 }
406 
JsGetShadowOffsetX(const JSCallbackInfo & info)407 void JSCanvasRenderer::JsGetShadowOffsetX(const JSCallbackInfo& info)
408 {
409     return;
410 }
411 
JsGetShadowOffsetY(const JSCallbackInfo & info)412 void JSCanvasRenderer::JsGetShadowOffsetY(const JSCallbackInfo& info)
413 {
414     return;
415 }
416 
JsGetImageSmoothingEnabled(const JSCallbackInfo & info)417 void JSCanvasRenderer::JsGetImageSmoothingEnabled(const JSCallbackInfo& info)
418 {
419     return;
420 }
421 
JsGetImageSmoothingQuality(const JSCallbackInfo & info)422 void JSCanvasRenderer::JsGetImageSmoothingQuality(const JSCallbackInfo& info)
423 {
424     return;
425 }
426 
JsSetFillStyle(const JSCallbackInfo & info)427 void JSCanvasRenderer::JsSetFillStyle(const JSCallbackInfo& info)
428 {
429     if (info.Length() < 1) {
430         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
431         return;
432     }
433     std::string type = "";
434     if (info[0]->IsString()) {
435         std::string colorStr = "";
436         JSViewAbstract::ParseJsString(info[0], colorStr);
437         auto color = Color::FromString(colorStr);
438         if (isOffscreen_) {
439             offscreenCanvas_->SetFillColor(color);
440         } else {
441             pool_->UpdateFillColor(color);
442         }
443     } else {
444         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
445         JSRef<JSVal> typeValue = obj->GetProperty("__type");
446         std::string type = "";
447         JSViewAbstract::ParseJsString(typeValue, type);
448         if (type == "gradient") {
449             JSCanvasGradient* jSCanvasGradient = JSRef<JSObject>::Cast(info[0])->Unwrap<JSCanvasGradient>();
450             if (!jSCanvasGradient) {
451                 return;
452             }
453             Gradient* gradient = jSCanvasGradient->GetGradient();
454             if (!gradient) {
455                 return;
456             }
457             if (isOffscreen_) {
458                 offscreenCanvas_->SetFillGradient(*gradient);
459             } else {
460                 pool_->UpdateFillGradient(*gradient);
461             }
462         } else if (type == "pattern") {
463             JSRef<JSVal> typeValue = obj->GetProperty("__id");
464             int32_t id;
465             ParseJsInt(typeValue, id);
466             auto pattern = GetPattern(id);
467             if (isOffscreen_) {
468                 offscreenCanvas_->SetFillPattern(pattern);
469             } else {
470                 pool_->UpdateFillPattern(pattern);
471             }
472         } else {
473             LOGW("unsupported function for stroke style.");
474         }
475     }
476 }
477 
JsSetStrokeStyle(const JSCallbackInfo & info)478 void JSCanvasRenderer::JsSetStrokeStyle(const JSCallbackInfo& info)
479 {
480     if (info.Length() < 1) {
481         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
482         return;
483     }
484 
485     std::string type = "";
486     if (info[0]->IsString()) {
487         std::string colorStr = "";
488         JSViewAbstract::ParseJsString(info[0], colorStr);
489         auto color = Color::FromString(colorStr);
490         if (isOffscreen_) {
491             offscreenCanvas_->SetStrokeColor(color);
492         } else {
493             pool_->UpdateStrokeColor(color);
494         }
495     } else {
496         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
497         JSRef<JSVal> typeValue = obj->GetProperty("__type");
498         std::string type = "";
499         JSViewAbstract::ParseJsString(typeValue, type);
500         if (type == "gradient") {
501             JSCanvasGradient* jSCanvasGradient = JSRef<JSObject>::Cast(info[0])->Unwrap<JSCanvasGradient>();
502             if (!jSCanvasGradient) {
503                 return;
504             }
505             Gradient* gradient = jSCanvasGradient->GetGradient();
506             if (!gradient) {
507                 return;
508             }
509             if (isOffscreen_) {
510                 offscreenCanvas_->SetStrokeGradient(*gradient);
511             } else {
512                 pool_->UpdateStrokeGradient(*gradient);
513             }
514         } else if (type == "pattern") {
515             JSRef<JSVal> typeValue = obj->GetProperty("__id");
516             int32_t id;
517             ParseJsInt(typeValue, id);
518             auto pattern = GetPattern(id);
519             if (isOffscreen_) {
520                 offscreenCanvas_->SetStrokePattern(pattern);
521             } else {
522                 pool_->UpdateStrokePattern(pattern);
523             }
524         } else {
525             LOGW("unsupported function for stroke style.");
526         }
527     }
528 }
529 
JsMakePath2D(const JSCallbackInfo & info)530 RefPtr<CanvasPath2D> JSCanvasRenderer::JsMakePath2D(const JSCallbackInfo& info)
531 {
532     if (info.Length() == 1) {
533         if (info[0]->IsString()) {
534             std::string capStr = "";
535             JSViewAbstract::ParseJsString(info[0], capStr);
536             return AceType::MakeRefPtr<CanvasPath2D>(capStr);
537         }
538     }
539     // Example: ctx.createPath2D()
540     return AceType::MakeRefPtr<CanvasPath2D>();
541 }
542 
JsDrawImage(const JSCallbackInfo & info)543 void JSCanvasRenderer::JsDrawImage(const JSCallbackInfo& info)
544 {
545     CanvasImage image;
546     double imgWidth;
547     double imgHeight;
548     RefPtr<PixelMap> pixelMap = nullptr;
549     bool isImage = false;
550     if (info[0]->IsObject()) {
551         JSRenderImage* jsImage = JSRef<JSObject>::Cast(info[0])->Unwrap<JSRenderImage>();
552         if (jsImage) {
553             isImage = true;
554             std::string imageValue = jsImage->GetSrc();
555             image.src = imageValue;
556             imgWidth = jsImage->GetWidth();
557             imgHeight = jsImage->GetHeight();
558         } else {
559 #if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM)
560             pixelMap = CreatePixelMapFromNapiValue(info[0]);
561 #endif
562             if (!pixelMap) {
563                 LOGE("pixelMap is null");
564                 return;
565             }
566         }
567 
568         switch (info.Length()) {
569             case 3:
570                 image.flag = 0;
571                 JSViewAbstract::ParseJsDouble(info[1], image.dx);
572                 JSViewAbstract::ParseJsDouble(info[2], image.dy);
573                 image.dx = SystemProperties::Vp2Px(image.dx);
574                 image.dy = SystemProperties::Vp2Px(image.dy);
575                 break;
576             // 5 parameters: drawImage(image, dx, dy, dWidth, dHeight)
577             case 5:
578                 image.flag = 1;
579                 JSViewAbstract::ParseJsDouble(info[1], image.dx);
580                 JSViewAbstract::ParseJsDouble(info[2], image.dy);
581                 JSViewAbstract::ParseJsDouble(info[3], image.dWidth);
582                 JSViewAbstract::ParseJsDouble(info[4], image.dHeight);
583                 image.dx = SystemProperties::Vp2Px(image.dx);
584                 image.dy = SystemProperties::Vp2Px(image.dy);
585                 image.dWidth = SystemProperties::Vp2Px(image.dWidth);
586                 image.dHeight = SystemProperties::Vp2Px(image.dHeight);
587                 break;
588             // 9 parameters: drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
589             case 9:
590                 image.flag = 2;
591                 JSViewAbstract::ParseJsDouble(info[1], image.sx);
592                 JSViewAbstract::ParseJsDouble(info[2], image.sy);
593                 JSViewAbstract::ParseJsDouble(info[3], image.sWidth);
594                 JSViewAbstract::ParseJsDouble(info[4], image.sHeight);
595                 JSViewAbstract::ParseJsDouble(info[5], image.dx);
596                 JSViewAbstract::ParseJsDouble(info[6], image.dy);
597                 JSViewAbstract::ParseJsDouble(info[7], image.dWidth);
598                 JSViewAbstract::ParseJsDouble(info[8], image.dHeight);
599                 if (isImage) {
600                     image.sx = SystemProperties::Vp2Px(image.sx);
601                     image.sy = SystemProperties::Vp2Px(image.sy);
602                     image.sWidth = SystemProperties::Vp2Px(image.sWidth);
603                     image.sHeight = SystemProperties::Vp2Px(image.sHeight);
604                 }
605                 image.dx = SystemProperties::Vp2Px(image.dx);
606                 image.dy = SystemProperties::Vp2Px(image.dy);
607                 image.dWidth = SystemProperties::Vp2Px(image.dWidth);
608                 image.dHeight = SystemProperties::Vp2Px(image.dHeight);
609                 break;
610             default:
611                 break;
612         }
613 
614         if (isOffscreen_) {
615             if (isImage) {
616                 offscreenCanvas_->DrawImage(image, imgWidth, imgHeight);
617             } else {
618                 offscreenCanvas_->DrawPixelMap(pixelMap, image);
619             }
620         } else {
621             if (isImage) {
622                 pool_->DrawImage(image, imgWidth, imgHeight);
623             } else {
624                 pool_->DrawPixelMap(pixelMap, image);
625             }
626         }
627     }
628 }
629 
JsCreatePattern(const JSCallbackInfo & info)630 void JSCanvasRenderer::JsCreatePattern(const JSCallbackInfo& info)
631 {
632     if (info[0]->IsObject()) {
633         JSRenderImage* jsImage = JSRef<JSObject>::Cast(info[0])->Unwrap<JSRenderImage>();
634         if (jsImage == nullptr) {
635             LOGE("jsImage is null");
636             return;
637         }
638         std::string imageSrc = jsImage->GetSrc();
639         double imgWidth = jsImage->GetWidth();
640         double imgHeight = jsImage->GetHeight();
641         std::string repeat;
642 
643         JSViewAbstract::ParseJsString(info[1], repeat);
644         pattern_[patternCount_].SetImgSrc(imageSrc);
645         pattern_[patternCount_].SetImageWidth(imgWidth);
646         pattern_[patternCount_].SetImageHeight(imgHeight);
647         pattern_[patternCount_].SetRepetition(repeat);
648 
649         auto retObj = JSRef<JSObject>::New();
650         retObj->SetProperty("__type", "pattern");
651         retObj->SetProperty("__id", patternCount_);
652         patternCount_++;
653         info.SetReturnValue(retObj);
654     }
655 }
656 
JsCreateImageData(const JSCallbackInfo & info)657 void JSCanvasRenderer::JsCreateImageData(const JSCallbackInfo& info)
658 {
659     double width = 0;
660     double height = 0;
661 
662     if (info.Length() == 2) {
663         JSViewAbstract::ParseJsDouble(info[0], width);
664         JSViewAbstract::ParseJsDouble(info[1], height);
665         width = SystemProperties::Vp2Px(width);
666         height = SystemProperties::Vp2Px(height);
667 
668     }
669     if (info.Length() == 1 && info[0]->IsObject()) {
670         width = imageData_.dirtyWidth;
671         height = imageData_.dirtyHeight;
672     }
673 
674     auto container = Container::Current();
675     if (!container) {
676         LOGW("container is null");
677         return;
678     }
679 
680     imageData_.dirtyWidth = width;
681     imageData_.dirtyHeight = height;
682 
683     JSRef<JSArray> colorArray = JSRef<JSArray>::New();
684     uint32_t count = 0;
685     for (auto i = 0; i < width; i++) {
686         for (auto j = 0; j < height; j++) {
687             colorArray->SetValueAt(count, JSRef<JSVal>::Make(ToJSValue(255)));
688             colorArray->SetValueAt(count + 1, JSRef<JSVal>::Make(ToJSValue(255)));
689             colorArray->SetValueAt(count + 2, JSRef<JSVal>::Make(ToJSValue(255)));
690             colorArray->SetValueAt(count + 3, JSRef<JSVal>::Make(ToJSValue(255)));
691             count += 4;
692         }
693     }
694 
695     auto retObj = JSRef<JSObject>::New();
696     retObj->SetProperty("width", width);
697     retObj->SetProperty("height", height);
698     retObj->SetPropertyObject("data", colorArray);
699     info.SetReturnValue(retObj);
700 }
701 
JsPutImageData(const JSCallbackInfo & info)702 void JSCanvasRenderer::JsPutImageData(const JSCallbackInfo& info)
703 {
704     if (info.Length() < 1) {
705         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
706         return;
707     }
708     int32_t width = 0;
709     int32_t height = 0;
710     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
711     JSRef<JSVal> widthValue = obj->GetProperty("width");
712     JSRef<JSVal> heightValue = obj->GetProperty("height");
713     ParseJsInt(widthValue, width);
714     ParseJsInt(heightValue, height);
715 
716     ImageData imageData;
717     std::vector<uint32_t> array;
718     ParseImageData(info, imageData, array);
719 
720     int64_t num = 0;
721     for (int32_t i = 0; i < height; ++i) {
722         for (int32_t j = 0; j < width; ++j) {
723             if ((i >= imageData.dirtyY) && (i - imageData.dirtyY < imageData.dirtyHeight) && (j >= imageData.dirtyX) &&
724                 (j - imageData.dirtyX < imageData.dirtyWidth)) {
725                 int32_t flag = j + width * i;
726                 if (array.size() > static_cast<uint32_t>(4 * flag + 3)) {
727                     auto red = array[4 * flag];
728                     auto green = array[4 * flag + 1];
729                     auto blue = array[4 * flag + 2];
730                     auto alpha = array[4 * flag + 3];
731                     if (num < imageData.dirtyWidth * imageData.dirtyHeight) {
732                         imageData.data.emplace_back(Color::FromARGB(alpha, red, green, blue));
733                     }
734                     num++;
735                 }
736             }
737         }
738     }
739 
740     if (isOffscreen_) {
741         offscreenCanvas_->PutImageData(imageData);
742     } else {
743         pool_->PutImageData(imageData);
744     }
745 }
746 
ParseImageData(const JSCallbackInfo & info,ImageData & imageData,std::vector<uint32_t> & array)747 void JSCanvasRenderer::ParseImageData(const JSCallbackInfo& info, ImageData& imageData, std::vector<uint32_t>& array)
748 {
749     int32_t width = 0;
750     int32_t height = 0;
751 
752     if (info[0]->IsObject()) {
753         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
754         JSRef<JSVal> widthValue = obj->GetProperty("width");
755         JSRef<JSVal> heightValue = obj->GetProperty("height");
756         JSRef<JSVal> dataValue = obj->GetProperty("data");
757         ParseJsInt(widthValue, width);
758         ParseJsInt(heightValue, height);
759         JSViewAbstract::ParseJsIntegerArray(dataValue, array);
760     }
761 
762     ParseJsInt(info[1], imageData.x);
763     ParseJsInt(info[2], imageData.y);
764     imageData.x = SystemProperties::Vp2Px(imageData.x);
765     imageData.y = SystemProperties::Vp2Px(imageData.y);
766 
767     imageData.dirtyWidth = width;
768     imageData.dirtyHeight = height;
769 
770     if (info.Length() == 7) {
771         ParseJsInt(info[3], imageData.dirtyX);
772         ParseJsInt(info[4], imageData.dirtyY);
773         ParseJsInt(info[5], imageData.dirtyWidth);
774         ParseJsInt(info[6], imageData.dirtyHeight);
775         imageData.dirtyX = SystemProperties::Vp2Px(imageData.dirtyX);
776         imageData.dirtyY = SystemProperties::Vp2Px(imageData.dirtyY);
777         imageData.dirtyWidth = SystemProperties::Vp2Px(imageData.dirtyWidth);
778         imageData.dirtyHeight = SystemProperties::Vp2Px(imageData.dirtyHeight);
779     }
780 
781     imageData.dirtyWidth = imageData.dirtyX < 0 ? std::min(imageData.dirtyX + imageData.dirtyWidth, width)
782                                                 : std::min(width - imageData.dirtyX, imageData.dirtyWidth);
783     imageData.dirtyHeight = imageData.dirtyY < 0 ? std::min(imageData.dirtyY + imageData.dirtyHeight, height)
784                                                  : std::min(height - imageData.dirtyY, imageData.dirtyHeight);
785 }
786 
JsGetImageData(const JSCallbackInfo & info)787 void JSCanvasRenderer::JsGetImageData(const JSCallbackInfo& info)
788 {
789     double left = 0.0;
790     double top = 0.0;
791     double width = 0.0;
792     double height = 0.0;
793     double final_width = 0.0;
794     double final_height = 0.0;
795 
796     JSViewAbstract::ParseJsDouble(info[0], left);
797     JSViewAbstract::ParseJsDouble(info[1], top);
798     JSViewAbstract::ParseJsDouble(info[2], width);
799     JSViewAbstract::ParseJsDouble(info[3], height);
800     left = SystemProperties::Vp2Px(left);
801     top = SystemProperties::Vp2Px(top);
802     width = SystemProperties::Vp2Px(width);
803     height = SystemProperties::Vp2Px(height);
804 
805     std::unique_ptr<ImageData> data;
806     if (isOffscreen_) {
807         data = offscreenCanvas_->GetImageData(left, top, width, height);
808     } else {
809         data = pool_->GetImageData(left, top, width, height);
810     }
811 
812     final_height = static_cast<uint32_t>(data->dirtyHeight);
813     final_width = static_cast<uint32_t>(data->dirtyWidth);
814 
815     JSRef<JSArray> colorArray = JSRef<JSArray>::New();
816     uint32_t count = 0;
817     for (uint32_t i = 0; i < final_height; i++) {
818         for (uint32_t j = 0; j < final_width; j++) {
819             int32_t idx = i * data->dirtyWidth + j;
820             auto pixel = data->data[idx];
821 
822             colorArray->SetValueAt(count, JSRef<JSVal>::Make(ToJSValue(pixel.GetRed())));
823             colorArray->SetValueAt(count + 1, JSRef<JSVal>::Make(ToJSValue(pixel.GetGreen())));
824             colorArray->SetValueAt(count + 2, JSRef<JSVal>::Make(ToJSValue(pixel.GetBlue())));
825             colorArray->SetValueAt(count + 3, JSRef<JSVal>::Make(ToJSValue(pixel.GetAlpha())));
826             count += 4;
827         }
828     }
829 
830     auto retObj = JSRef<JSObject>::New();
831     retObj->SetProperty("width", final_width);
832     retObj->SetProperty("height", final_height);
833     retObj->SetPropertyObject("data", colorArray);
834     info.SetReturnValue(retObj);
835 }
836 
JsGetPixelMap(const JSCallbackInfo & info)837 void JSCanvasRenderer::JsGetPixelMap(const JSCallbackInfo& info)
838 {
839 #ifdef PIXEL_MAP_SUPPORTED
840     // 0 Get input param
841     double fLeft = 0.0;
842     double fTop = 0.0;
843     double fWidth = 0.0;
844     double fHeight = 0.0;
845     int32_t left = 0;
846     int32_t top = 0;
847     int32_t width = 0;
848     int32_t height = 0;
849     uint32_t final_width = 0.0;
850     uint32_t final_height = 0.0;
851 
852     JSViewAbstract::ParseJsDouble(info[0], fLeft);
853     JSViewAbstract::ParseJsDouble(info[1], fTop);
854     JSViewAbstract::ParseJsDouble(info[2], fWidth);
855     JSViewAbstract::ParseJsDouble(info[3], fHeight);
856 
857     fLeft = SystemProperties::Vp2Px(fLeft);
858     fTop = SystemProperties::Vp2Px(fTop);
859     fWidth = SystemProperties::Vp2Px(fWidth);
860     fHeight = SystemProperties::Vp2Px(fHeight);
861 
862     left = fLeft;
863     top = fTop;
864     width = round(fWidth);
865     height = round(fHeight);
866 
867     // 1 Get data from canvas
868     std::unique_ptr<ImageData> canvasData;
869 
870     if (isOffscreen_) {
871         canvasData = offscreenCanvas_->GetImageData(left, top, width, height);
872     } else {
873         canvasData = pool_->GetImageData(left, top, width, height);
874     }
875     final_height = static_cast<uint32_t>(canvasData->dirtyHeight);
876     final_width = static_cast<uint32_t>(canvasData->dirtyWidth);
877     uint32_t length = final_height * final_width;
878     uint32_t* data = new uint32_t[length];
879     for (uint32_t i = 0; i < final_height; i++) {
880         for (uint32_t j = 0; j < final_width; j++) {
881             uint32_t idx = i * final_width + j;
882             Color pixel = canvasData->data[idx];
883             data[idx] = pixel.GetValue();
884         }
885     }
886 
887     // 2 Create pixelmap
888     OHOS::Media::InitializationOptions options;
889     options.alphaType = OHOS::Media::AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
890     options.pixelFormat = OHOS::Media::PixelFormat::RGBA_8888;
891     options.scaleMode = OHOS::Media::ScaleMode::CENTER_CROP;
892     options.size.width = static_cast<int32_t>(final_width);
893     options.size.height = static_cast<int32_t>(final_height);
894     options.editable = true;
895     std::unique_ptr<OHOS::Media::PixelMap> pixelmap = OHOS::Media::PixelMap::Create(data, length, options);
896 
897     // 3 pixelmap to NapiValue
898     auto engine = EngineHelper::GetCurrentEngine();
899     if (!engine) {
900         LOGE("JsGetPixelMap engine is null");
901         return;
902     }
903     NativeEngine* nativeEngine = engine->GetNativeEngine();
904     napi_env env = reinterpret_cast<napi_env>(nativeEngine);
905     std::shared_ptr<OHOS::Media::PixelMap> sharedPixelmap(pixelmap.release());
906     napi_value napiValue = OHOS::Media::PixelMapNapi::CreatePixelMap(env, sharedPixelmap);
907 
908     // 4 NapiValue to JsValue
909 #ifdef USE_ARK_ENGINE
910     NativeValue* nativeValue = reinterpret_cast<NativeValue*>(napiValue);
911     auto jsValue = JsConverter::ConvertNativeValueToJsVal(nativeValue);
912     info.SetReturnValue(jsValue);
913 #else
914     napi_value temp = nullptr;
915     napi_create_int32(env, 0, &temp);
916     napi_set_named_property(env, napiValue, "index", temp);
917 #endif
918 
919 #endif
920 }
921 
JsGetJsonData(const JSCallbackInfo & info)922 void JSCanvasRenderer::JsGetJsonData(const JSCallbackInfo& info)
923 {
924     std::string path = "";
925     std::string jsonData = "";
926 
927     if (info[0]->IsString()) {
928         JSViewAbstract::ParseJsString(info[0], path);
929         if (!isOffscreen_) {
930             jsonData = pool_->GetJsonData(path);
931         }
932         auto returnValue = JSVal(ToJSValue(jsonData));
933         auto returnPtr = JSRef<JSVal>::Make(returnValue);
934         info.SetReturnValue(returnPtr);
935     }
936 }
937 
JsToDataUrl(const JSCallbackInfo & info)938 void JSCanvasRenderer::JsToDataUrl(const JSCallbackInfo& info)
939 {
940     std::string dataUrl = "";
941     std::string result = "";
942     double quality = DEFAULT_QUALITY;
943     if (info[0]->IsString()) {
944         JSViewAbstract::ParseJsString(info[0], dataUrl);
945     }
946     if (info.Length() > 1 && info[1]->IsNumber()) {
947         JSViewAbstract::ParseJsDouble(info[1], quality);
948     }
949     if (isOffscreen_) {
950         result = offscreenCanvas_->ToDataURL(dataUrl, quality);
951     } else {
952         result = pool_->ToDataURL(dataUrl + "," + std::to_string(quality));
953     }
954     auto returnValue = JSVal(ToJSValue(result));
955     auto returnPtr = JSRef<JSVal>::Make(returnValue);
956     info.SetReturnValue(returnPtr);
957 }
958 
JsSetLineCap(const JSCallbackInfo & info)959 void JSCanvasRenderer::JsSetLineCap(const JSCallbackInfo& info)
960 {
961     if (info[0]->IsString()) {
962         std::string capStr = "";
963         JSViewAbstract::ParseJsString(info[0], capStr);
964         static const LinearMapNode<LineCapStyle> lineCapTable[] = {
965             { "butt", LineCapStyle::BUTT },
966             { "round", LineCapStyle::ROUND },
967             { "square", LineCapStyle::SQUARE },
968         };
969         auto lineCap = ConvertStrToEnum(capStr.c_str(), lineCapTable, ArraySize(lineCapTable), LineCapStyle::BUTT);
970         if (isOffscreen_) {
971             offscreenCanvas_->SetLineCap(lineCap);
972         } else {
973             pool_->UpdateLineCap(lineCap);
974         }
975     }
976 }
977 
JsSetLineJoin(const JSCallbackInfo & info)978 void JSCanvasRenderer::JsSetLineJoin(const JSCallbackInfo& info)
979 {
980     if (info[0]->IsString()) {
981         std::string joinStr = "";
982         JSViewAbstract::ParseJsString(info[0], joinStr);
983         static const LinearMapNode<LineJoinStyle> lineJoinTable[3] = {
984             { "bevel", LineJoinStyle::BEVEL },
985             { "miter", LineJoinStyle::MITER },
986             { "round", LineJoinStyle::ROUND },
987         };
988         auto lineJoin = ConvertStrToEnum(
989             joinStr.c_str(), lineJoinTable, ArraySize(lineJoinTable), LineJoinStyle::MITER);
990         if (isOffscreen_) {
991             offscreenCanvas_->SetLineJoin(lineJoin);
992         } else {
993             pool_->UpdateLineJoin(lineJoin);
994         }
995     }
996 }
997 
JsSetMiterLimit(const JSCallbackInfo & info)998 void JSCanvasRenderer::JsSetMiterLimit(const JSCallbackInfo& info)
999 {
1000     if (info[0]->IsNumber()) {
1001         double limit = 0.0;
1002         JSViewAbstract::ParseJsDouble(info[0], limit);
1003         limit = SystemProperties::Vp2Px(limit);
1004         if (isOffscreen_) {
1005             offscreenCanvas_->SetMiterLimit(limit);
1006         } else {
1007             pool_->UpdateMiterLimit(limit);
1008         }
1009     }
1010 }
1011 
JsSetLineWidth(const JSCallbackInfo & info)1012 void JSCanvasRenderer::JsSetLineWidth(const JSCallbackInfo& info)
1013 {
1014     if (info[0]->IsNumber()) {
1015         double lineWidth = 0.0;
1016         JSViewAbstract::ParseJsDouble(info[0], lineWidth);
1017         lineWidth = SystemProperties::Vp2Px(lineWidth);
1018         if (isOffscreen_) {
1019             offscreenCanvas_->SetLineWidth(lineWidth);
1020         } else {
1021             pool_->UpdateLineWidth(lineWidth);
1022         }
1023     }
1024 }
1025 
JsSetGlobalAlpha(const JSCallbackInfo & info)1026 void JSCanvasRenderer::JsSetGlobalAlpha(const JSCallbackInfo& info)
1027 {
1028     if (info[0]->IsNumber()) {
1029         double alpha = 0.0;
1030         JSViewAbstract::ParseJsDouble(info[0], alpha);
1031         if (isOffscreen_) {
1032             offscreenCanvas_->SetAlpha(alpha);
1033         } else {
1034             pool_->UpdateGlobalAlpha(alpha);
1035         }
1036     }
1037 }
1038 
JsSetGlobalCompositeOperation(const JSCallbackInfo & info)1039 void JSCanvasRenderer::JsSetGlobalCompositeOperation(const JSCallbackInfo& info)
1040 {
1041     if (info[0]->IsString()) {
1042         std::string compositeStr = "";
1043         JSViewAbstract::ParseJsString(info[0], compositeStr);
1044 
1045         static const LinearMapNode<CompositeOperation> compositeOperationTable[] = {
1046         { "copy", CompositeOperation::COPY },
1047         { "destination-atop", CompositeOperation::DESTINATION_ATOP },
1048         { "destination-in", CompositeOperation::DESTINATION_IN },
1049         { "destination-out", CompositeOperation::DESTINATION_OUT },
1050         { "destination-over", CompositeOperation::DESTINATION_OVER },
1051         { "lighter", CompositeOperation::LIGHTER },
1052         { "source-atop", CompositeOperation::SOURCE_ATOP },
1053 
1054         { "source-in", CompositeOperation::SOURCE_IN },
1055         { "source-out", CompositeOperation::SOURCE_OUT },
1056         { "source-over", CompositeOperation::SOURCE_OVER },
1057         { "xor", CompositeOperation::XOR },
1058         };
1059         auto type = ConvertStrToEnum(
1060             compositeStr.c_str(), compositeOperationTable,
1061             ArraySize(compositeOperationTable), CompositeOperation::SOURCE_OVER);
1062         if (isOffscreen_) {
1063             offscreenCanvas_->SetCompositeType(type);
1064         } else {
1065             pool_->UpdateCompositeOperation(type);
1066         }
1067     }
1068 }
1069 
JsSetLineDashOffset(const JSCallbackInfo & info)1070 void JSCanvasRenderer::JsSetLineDashOffset(const JSCallbackInfo& info)
1071 {
1072     if (info[0]->IsNumber()) {
1073         double lineDashOffset = 0.0;
1074         JSViewAbstract::ParseJsDouble(info[0], lineDashOffset);
1075         lineDashOffset = SystemProperties::Vp2Px(lineDashOffset);
1076         if (isOffscreen_) {
1077             offscreenCanvas_->SetLineDashOffset(lineDashOffset);
1078         } else {
1079             pool_->UpdateLineDashOffset(lineDashOffset);
1080         }
1081     }
1082 }
1083 
JsSetShadowBlur(const JSCallbackInfo & info)1084 void JSCanvasRenderer::JsSetShadowBlur(const JSCallbackInfo& info)
1085 {
1086     if (info[0]->IsNumber()) {
1087         double blur = 0.0;
1088         JSViewAbstract::ParseJsDouble(info[0], blur);
1089         if (isOffscreen_) {
1090             offscreenCanvas_->SetShadowBlur(blur);
1091         } else {
1092             pool_->UpdateShadowBlur(blur);
1093         }
1094     }
1095 }
1096 
JsSetShadowColor(const JSCallbackInfo & info)1097 void JSCanvasRenderer::JsSetShadowColor(const JSCallbackInfo& info)
1098 {
1099     if (info[0]->IsString()) {
1100         std::string colorStr = "";
1101         JSViewAbstract::ParseJsString(info[0], colorStr);
1102         auto color = Color::FromString(colorStr);
1103         if (isOffscreen_) {
1104             offscreenCanvas_->SetShadowColor(color);
1105         } else {
1106             pool_->UpdateShadowColor(color);
1107         }
1108     }
1109 }
1110 
JsSetShadowOffsetX(const JSCallbackInfo & info)1111 void JSCanvasRenderer::JsSetShadowOffsetX(const JSCallbackInfo& info)
1112 {
1113     if (info[0]->IsNumber()) {
1114         double offsetX = 0.0;
1115         JSViewAbstract::ParseJsDouble(info[0], offsetX);
1116         offsetX = SystemProperties::Vp2Px(offsetX);
1117         if (isOffscreen_) {
1118             offscreenCanvas_->SetShadowOffsetX(offsetX);
1119         } else {
1120             pool_->UpdateShadowOffsetX(offsetX);
1121         }
1122     }
1123 }
1124 
JsSetShadowOffsetY(const JSCallbackInfo & info)1125 void JSCanvasRenderer::JsSetShadowOffsetY(const JSCallbackInfo& info)
1126 {
1127     if (info[0]->IsNumber()) {
1128         double offsetY = 0.0;
1129         JSViewAbstract::ParseJsDouble(info[0], offsetY);
1130         offsetY = SystemProperties::Vp2Px(offsetY);
1131         if (isOffscreen_) {
1132             offscreenCanvas_->SetShadowOffsetY(offsetY);
1133         } else {
1134             pool_->UpdateShadowOffsetY(offsetY);
1135         }
1136     }
1137 }
1138 
JsSetImageSmoothingEnabled(const JSCallbackInfo & info)1139 void JSCanvasRenderer::JsSetImageSmoothingEnabled(const JSCallbackInfo& info)
1140 {
1141     if (info.Length() < 1) {
1142         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
1143         return;
1144     }
1145 
1146     bool enabled = false;
1147     if (JSViewAbstract::ParseJsBool(info[0], enabled)) {
1148         if (isOffscreen_) {
1149             offscreenCanvas_->SetSmoothingEnabled(enabled);
1150         } else {
1151             pool_->UpdateSmoothingEnabled(enabled);
1152         }
1153     }
1154 }
1155 
JsSetImageSmoothingQuality(const JSCallbackInfo & info)1156 void JSCanvasRenderer::JsSetImageSmoothingQuality(const JSCallbackInfo& info)
1157 {
1158     if (info.Length() < 1) {
1159         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
1160         return;
1161     }
1162 
1163     std::string quality = "";
1164     if (JSViewAbstract::ParseJsString(info[0], quality)) {
1165         if (QUALITY_TYPE.find(quality) == QUALITY_TYPE.end()) {
1166             return;
1167         }
1168         if (isOffscreen_) {
1169             offscreenCanvas_->SetSmoothingQuality(quality);
1170         } else {
1171             pool_->UpdateSmoothingQuality(quality);
1172         }
1173     }
1174 }
1175 
JsMoveTo(const JSCallbackInfo & info)1176 void JSCanvasRenderer::JsMoveTo(const JSCallbackInfo& info)
1177 {
1178     if (info.Length() < 1) {
1179         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1180         return;
1181     }
1182 
1183     if (info[0]->IsNumber() && info[1]->IsNumber()) {
1184         double x = 0.0;
1185         double y = 0.0;
1186         JSViewAbstract::ParseJsDouble(info[0], x);
1187         JSViewAbstract::ParseJsDouble(info[1], y);
1188         x = SystemProperties::Vp2Px(x);
1189         y = SystemProperties::Vp2Px(y);
1190         if (isOffscreen_) {
1191             offscreenCanvas_->MoveTo(x, y);
1192         } else {
1193             pool_->MoveTo(x, y);
1194         }
1195     }
1196 }
1197 
JsLineTo(const JSCallbackInfo & info)1198 void JSCanvasRenderer::JsLineTo(const JSCallbackInfo& info)
1199 {
1200     if (info.Length() < 1) {
1201         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1202         return;
1203     }
1204 
1205     if (info[0]->IsNumber() && info[1]->IsNumber()) {
1206         double x = 0.0;
1207         double y = 0.0;
1208         JSViewAbstract::ParseJsDouble(info[0], x);
1209         JSViewAbstract::ParseJsDouble(info[1], y);
1210         x = SystemProperties::Vp2Px(x);
1211         y = SystemProperties::Vp2Px(y);
1212         if (isOffscreen_) {
1213             offscreenCanvas_->LineTo(x, y);
1214         } else {
1215             pool_->LineTo(x, y);
1216         }
1217     }
1218 }
1219 
JsBezierCurveTo(const JSCallbackInfo & info)1220 void JSCanvasRenderer::JsBezierCurveTo(const JSCallbackInfo& info)
1221 {
1222     if (info.Length() < 1) {
1223         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1224         return;
1225     }
1226 
1227     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()
1228         && info[4]->IsNumber() && info[5]->IsNumber()) {
1229         BezierCurveParam param;
1230         JSViewAbstract::ParseJsDouble(info[0], param.cp1x);
1231         JSViewAbstract::ParseJsDouble(info[1], param.cp1y);
1232         JSViewAbstract::ParseJsDouble(info[2], param.cp2x);
1233         JSViewAbstract::ParseJsDouble(info[3], param.cp2y);
1234         JSViewAbstract::ParseJsDouble(info[4], param.x);
1235         JSViewAbstract::ParseJsDouble(info[5], param.y);
1236         param.cp1x = SystemProperties::Vp2Px(param.cp1x);
1237         param.cp1y = SystemProperties::Vp2Px(param.cp1y);
1238         param.cp2x = SystemProperties::Vp2Px(param.cp2x);
1239         param.cp2y = SystemProperties::Vp2Px(param.cp2y);
1240         param.x = SystemProperties::Vp2Px(param.x);
1241         param.y = SystemProperties::Vp2Px(param.y);
1242 
1243         if (isOffscreen_) {
1244             offscreenCanvas_->BezierCurveTo(param);
1245         } else {
1246             pool_->BezierCurveTo(param);
1247         }
1248     }
1249 }
1250 
JsQuadraticCurveTo(const JSCallbackInfo & info)1251 void JSCanvasRenderer::JsQuadraticCurveTo(const JSCallbackInfo& info)
1252 {
1253     if (info.Length() < 1) {
1254         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1255         return;
1256     }
1257 
1258     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()) {
1259         QuadraticCurveParam param;
1260         JSViewAbstract::ParseJsDouble(info[0], param.cpx);
1261         JSViewAbstract::ParseJsDouble(info[1], param.cpy);
1262         JSViewAbstract::ParseJsDouble(info[2], param.x);
1263         JSViewAbstract::ParseJsDouble(info[3], param.y);
1264         param.cpx = SystemProperties::Vp2Px(param.cpx);
1265         param.cpy = SystemProperties::Vp2Px(param.cpy);
1266         param.x = SystemProperties::Vp2Px(param.x);
1267         param.y = SystemProperties::Vp2Px(param.y);
1268 
1269         if (isOffscreen_) {
1270             offscreenCanvas_->QuadraticCurveTo(param);
1271         } else {
1272             pool_->QuadraticCurveTo(param);
1273         }
1274     }
1275 }
1276 
JsArcTo(const JSCallbackInfo & info)1277 void JSCanvasRenderer::JsArcTo(const JSCallbackInfo& info)
1278 {
1279     if (info.Length() < 1) {
1280         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1281         return;
1282     }
1283 
1284     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()
1285         && info[4]->IsNumber()) {
1286         ArcToParam param;
1287         JSViewAbstract::ParseJsDouble(info[0], param.x1);
1288         JSViewAbstract::ParseJsDouble(info[1], param.y1);
1289         JSViewAbstract::ParseJsDouble(info[2], param.x2);
1290         JSViewAbstract::ParseJsDouble(info[3], param.y2);
1291         JSViewAbstract::ParseJsDouble(info[4], param.radius);
1292         param.x1 = SystemProperties::Vp2Px(param.x1);
1293         param.y1 = SystemProperties::Vp2Px(param.y1);
1294         param.x2 = SystemProperties::Vp2Px(param.x2);
1295         param.y2 = SystemProperties::Vp2Px(param.y2);
1296         param.radius = SystemProperties::Vp2Px(param.radius);
1297 
1298         if (isOffscreen_) {
1299             offscreenCanvas_->ArcTo(param);
1300         } else {
1301             pool_->ArcTo(param);
1302         }
1303     }
1304 }
1305 
JsArc(const JSCallbackInfo & info)1306 void JSCanvasRenderer::JsArc(const JSCallbackInfo& info)
1307 {
1308     if (info.Length() < 1) {
1309         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1310         return;
1311     }
1312 
1313     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()
1314         && info[4]->IsNumber()) {
1315         ArcParam param;
1316         JSViewAbstract::ParseJsDouble(info[0], param.x);
1317         JSViewAbstract::ParseJsDouble(info[1], param.y);
1318         JSViewAbstract::ParseJsDouble(info[2], param.radius);
1319         JSViewAbstract::ParseJsDouble(info[3], param.startAngle);
1320         JSViewAbstract::ParseJsDouble(info[4], param.endAngle);
1321         param.x = SystemProperties::Vp2Px(param.x);
1322         param.y = SystemProperties::Vp2Px(param.y);
1323         param.radius = SystemProperties::Vp2Px(param.radius);
1324 
1325         if (info.Length() == 6) {
1326             JSViewAbstract::ParseJsBool(info[5], param.anticlockwise);
1327         }
1328         if (isOffscreen_) {
1329             offscreenCanvas_->Arc(param);
1330         } else {
1331             pool_->Arc(param);
1332         }
1333     }
1334 }
1335 
JsEllipse(const JSCallbackInfo & info)1336 void JSCanvasRenderer::JsEllipse(const JSCallbackInfo& info)
1337 {
1338     if (info.Length() < 1) {
1339         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1340         return;
1341     }
1342 
1343     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()
1344         && info[4]->IsNumber() && info[5]->IsNumber() && info[6]->IsNumber()) {
1345         EllipseParam param;
1346         JSViewAbstract::ParseJsDouble(info[0], param.x);
1347         JSViewAbstract::ParseJsDouble(info[1], param.y);
1348         JSViewAbstract::ParseJsDouble(info[2], param.radiusX);
1349         JSViewAbstract::ParseJsDouble(info[3], param.radiusY);
1350         JSViewAbstract::ParseJsDouble(info[4], param.rotation);
1351         JSViewAbstract::ParseJsDouble(info[5], param.startAngle);
1352         JSViewAbstract::ParseJsDouble(info[6], param.endAngle);
1353         param.x = SystemProperties::Vp2Px(param.x);
1354         param.y = SystemProperties::Vp2Px(param.y);
1355         param.radiusX = SystemProperties::Vp2Px(param.radiusX);
1356         param.radiusY = SystemProperties::Vp2Px(param.radiusY);
1357 
1358         if (info.Length() == 8) {
1359             JSViewAbstract::ParseJsBool(info[7], param.anticlockwise);
1360         }
1361         if (isOffscreen_) {
1362             offscreenCanvas_->Ellipse(param);
1363         } else {
1364             pool_->Ellipse(param);
1365         }
1366     }
1367 }
1368 
JsFill(const JSCallbackInfo & info)1369 void JSCanvasRenderer::JsFill(const JSCallbackInfo& info)
1370 {
1371     if (isOffscreen_) {
1372         offscreenCanvas_->Fill();
1373     } else {
1374         pool_->Fill();
1375     }
1376 }
1377 
JsStroke(const JSCallbackInfo & info)1378 void JSCanvasRenderer::JsStroke(const JSCallbackInfo& info)
1379 {
1380     if (info.Length() == 1) {
1381         JSPath2D* jsCanvasPath = JSRef<JSObject>::Cast(info[0])->Unwrap<JSPath2D>();
1382         auto path = jsCanvasPath->GetCanvasPath2d();
1383         if (isOffscreen_) {
1384             offscreenCanvas_->Stroke(path);
1385         } else {
1386             pool_->Stroke(path);
1387         }
1388         return;
1389     }
1390     if (isOffscreen_) {
1391         offscreenCanvas_->Stroke();
1392     } else {
1393         pool_->Stroke();
1394     }
1395 }
1396 
JsClip(const JSCallbackInfo & info)1397 void JSCanvasRenderer::JsClip(const JSCallbackInfo& info)
1398 {
1399     if (isOffscreen_) {
1400         offscreenCanvas_->Clip();
1401     } else {
1402         pool_->Clip();
1403     }
1404 }
1405 
JsRect(const JSCallbackInfo & info)1406 void JSCanvasRenderer::JsRect(const JSCallbackInfo& info)
1407 {
1408     Rect rect = GetJsRectParam(info);
1409     if (isOffscreen_) {
1410         offscreenCanvas_->AddRect(rect);
1411     } else {
1412         pool_->AddRect(rect);
1413     }
1414 }
1415 
JsBeginPath(const JSCallbackInfo & info)1416 void JSCanvasRenderer::JsBeginPath(const JSCallbackInfo& info)
1417 {
1418     if (info.Length() != 0) {
1419         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
1420         return;
1421     }
1422     if (isOffscreen_) {
1423         offscreenCanvas_->BeginPath();
1424     } else {
1425         pool_->BeginPath();
1426     }
1427 }
1428 
JsClosePath(const JSCallbackInfo & info)1429 void JSCanvasRenderer::JsClosePath(const JSCallbackInfo& info)
1430 {
1431     if (info.Length() != 0) {
1432         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
1433         return;
1434     }
1435     if (isOffscreen_) {
1436         offscreenCanvas_->ClosePath();
1437     } else {
1438         pool_->ClosePath();
1439     }
1440 }
1441 
JsRestore(const JSCallbackInfo & info)1442 void JSCanvasRenderer::JsRestore(const JSCallbackInfo& info)
1443 {
1444     if (info.Length() != 0) {
1445         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
1446         return;
1447     }
1448     if (isOffscreen_) {
1449         offscreenCanvas_->Restore();
1450     } else {
1451         pool_->Restore();
1452     }
1453 }
1454 
JsSave(const JSCallbackInfo & info)1455 void JSCanvasRenderer::JsSave(const JSCallbackInfo& info)
1456 {
1457     if (info.Length() != 0) {
1458         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
1459         return;
1460     }
1461     if (isOffscreen_) {
1462         offscreenCanvas_->Save();
1463     } else {
1464         pool_->Save();
1465     }
1466 }
1467 
JsRotate(const JSCallbackInfo & info)1468 void JSCanvasRenderer::JsRotate(const JSCallbackInfo& info)
1469 {
1470     if (info.Length() != 1) {
1471         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
1472         return;
1473     }
1474     double angle = 0.0;
1475     JSViewAbstract::ParseJsDouble(info[0], angle);
1476     if (isOffscreen_) {
1477         offscreenCanvas_->Rotate(angle);
1478     } else {
1479         pool_->Rotate(angle);
1480     }
1481 }
1482 
JsScale(const JSCallbackInfo & info)1483 void JSCanvasRenderer::JsScale(const JSCallbackInfo& info)
1484 {
1485     if (info.Length() < 1) {
1486         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1487         return;
1488     }
1489 
1490     if (info[0]->IsNumber() && info[1]->IsNumber()) {
1491         double x = 0.0;
1492         double y = 0.0;
1493         JSViewAbstract::ParseJsDouble(info[0], x);
1494         JSViewAbstract::ParseJsDouble(info[1], y);
1495         if (isOffscreen_) {
1496             offscreenCanvas_->Scale(x, y);
1497         } else {
1498             pool_->Scale(x, y);
1499         }
1500     }
1501 }
1502 
JsSetTransform(const JSCallbackInfo & info)1503 void JSCanvasRenderer::JsSetTransform(const JSCallbackInfo& info)
1504 {
1505     if (info.Length() == 6) {
1506         if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()
1507             && info[4]->IsNumber() && info[5]->IsNumber()) {
1508             TransformParam param;
1509             JSViewAbstract::ParseJsDouble(info[0], param.scaleX);
1510             JSViewAbstract::ParseJsDouble(info[1], param.skewX);
1511             JSViewAbstract::ParseJsDouble(info[2], param.skewY);
1512             JSViewAbstract::ParseJsDouble(info[3], param.scaleY);
1513             JSViewAbstract::ParseJsDouble(info[4], param.translateX);
1514             JSViewAbstract::ParseJsDouble(info[5], param.translateY);
1515             param.translateX = SystemProperties::Vp2Px(param.translateX);
1516             param.translateY = SystemProperties::Vp2Px(param.translateY);
1517 
1518             if (isOffscreen_) {
1519                 offscreenCanvas_->SetTransform(param);
1520             } else {
1521                 pool_->SetTransform(param);
1522             }
1523         }
1524     } else if (info.Length() == 1) {
1525         if (info[0]->IsObject()) {
1526             JSMatrix2d* jsContext = JSRef<JSObject>::Cast(info[0])->Unwrap<JSMatrix2d>();
1527             if (jsContext) {
1528                 TransformParam param;
1529                 param.scaleX = jsContext->JsGetScaleX();
1530                 param.skewX = jsContext->JsGetRotateY();
1531                 param.skewY = jsContext->JsGetRotateX();
1532                 param.scaleY = jsContext->JsGetScaleY();
1533                 param.translateX = jsContext->JsGetTranslateX();
1534                 param.translateY = jsContext->JsGetTranslateY();
1535                 if (isOffscreen_) {
1536                     offscreenCanvas_->SetTransform(param);
1537                 } else {
1538                     pool_->SetTransform(param);
1539                 }
1540             }
1541         }
1542     } else {
1543         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1544         return;
1545     }
1546 }
1547 
JsTransform(const JSCallbackInfo & info)1548 void JSCanvasRenderer::JsTransform(const JSCallbackInfo& info)
1549 {
1550     if (info.Length() < 6) {
1551         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1552         return;
1553     }
1554 
1555     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber() &&
1556         info[4]->IsNumber() && info[5]->IsNumber()) {
1557         TransformParam param;
1558         JSViewAbstract::ParseJsDouble(info[0], param.scaleX);
1559         JSViewAbstract::ParseJsDouble(info[1], param.skewX);
1560         JSViewAbstract::ParseJsDouble(info[2], param.skewY);
1561         JSViewAbstract::ParseJsDouble(info[3], param.scaleY);
1562         JSViewAbstract::ParseJsDouble(info[4], param.translateX);
1563         JSViewAbstract::ParseJsDouble(info[5], param.translateY);
1564         param.translateX = SystemProperties::Vp2Px(param.translateX);
1565         param.translateY = SystemProperties::Vp2Px(param.translateY);
1566 
1567         if (isOffscreen_) {
1568             offscreenCanvas_->Transform(param);
1569         } else {
1570             pool_->Transform(param);
1571         }
1572     }
1573 }
1574 
JsTranslate(const JSCallbackInfo & info)1575 void JSCanvasRenderer::JsTranslate(const JSCallbackInfo& info)
1576 {
1577     if (info.Length() < 2) {
1578         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
1579         return;
1580     }
1581 
1582     if (info[0]->IsNumber() && info[1]->IsNumber()) {
1583         double x = 0.0;
1584         double y = 0.0;
1585         JSViewAbstract::ParseJsDouble(info[0], x);
1586         JSViewAbstract::ParseJsDouble(info[1], y);
1587         x = SystemProperties::Vp2Px(x);
1588         y = SystemProperties::Vp2Px(y);
1589         if (isOffscreen_) {
1590             offscreenCanvas_->Translate(x, y);
1591         } else {
1592             pool_->Translate(x, y);
1593         }
1594     }
1595 }
1596 
JsSetLineDash(const JSCallbackInfo & info)1597 void JSCanvasRenderer::JsSetLineDash(const JSCallbackInfo& info)
1598 {
1599     std::vector<double> lineDash;
1600     ParseJsDoubleArray(info[0], lineDash);
1601 
1602     if (lineDash.size() % 2 != 0) {
1603         lineDash.insert(lineDash.end(), lineDash.begin(), lineDash.end());
1604     }
1605 
1606     if (isOffscreen_) {
1607         offscreenCanvas_->SetLineDash(lineDash);
1608     } else {
1609         pool_->UpdateLineDash(lineDash);
1610     }
1611 }
1612 
GetPattern(int32_t id)1613 Pattern JSCanvasRenderer::GetPattern(int32_t id)
1614 {
1615     if (id < 0) {
1616         return Pattern();
1617     }
1618     return pattern_[id];
1619 }
1620 
JsSetTextAlign(const JSCallbackInfo & info)1621 void JSCanvasRenderer::JsSetTextAlign(const JSCallbackInfo& info)
1622 {
1623     if (info.Length() < 1) {
1624         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
1625         return;
1626     }
1627     std::string value = "";
1628     if (info[0]->IsString()) {
1629         JSViewAbstract::ParseJsString(info[0], value);
1630         auto align = ConvertStrToTextAlign(value);
1631 
1632         if (isOffscreen_) {
1633             offscreenCanvas_->SetTextAlign(align);
1634         } else {
1635             pool_->UpdateTextAlign(align);
1636         }
1637         paintState_.SetTextAlign(align);
1638     }
1639 }
1640 
JsSetTextBaseline(const JSCallbackInfo & info)1641 void JSCanvasRenderer::JsSetTextBaseline(const JSCallbackInfo& info)
1642 {
1643     if (info.Length() < 1) {
1644         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
1645         return;
1646     }
1647 
1648     std::string textBaseline;
1649     if (info[0]->IsString()) {
1650         JSViewAbstract::ParseJsString(info[0], textBaseline);
1651         auto baseline = ConvertStrToEnum(
1652             textBaseline.c_str(), BASELINE_TABLE, ArraySize(BASELINE_TABLE), TextBaseline::ALPHABETIC);
1653 
1654         if (isOffscreen_) {
1655             offscreenCanvas_->SetTextBaseline(baseline);
1656         } else {
1657             pool_->UpdateTextBaseline(baseline);
1658         }
1659         style_.SetTextBaseline(baseline);
1660     }
1661 }
1662 
JsMeasureText(const JSCallbackInfo & info)1663 void JSCanvasRenderer::JsMeasureText(const JSCallbackInfo& info)
1664 {
1665     std::string text = "";
1666     paintState_.SetTextStyle(style_);
1667     double width = 0.0;
1668     double height = 0.0;
1669     double actualBoundingBoxLeft = 0.0;
1670     double actualBoundingBoxRight = 0.0;
1671     double actualBoundingBoxAscent = 0.0;
1672     double actualBoundingBoxDescent = 0.0;
1673     double hangingBaseline = 0.0;
1674     double alphabeticBaseline = 0.0;
1675     double ideographicBaseline = 0.0;
1676     double emHeightAscent = 0.0;
1677     double emHeightDescent = 0.0;
1678     double fontBoundingBoxAscent = 0.0;
1679     double fontBoundingBoxDescent = 0.0;
1680     if (info[0]->IsString()) {
1681         JSViewAbstract::ParseJsString(info[0], text);
1682         if (isOffscreen_) {
1683             width = offscreenCanvas_->MeasureText(text, paintState_);
1684             height = offscreenCanvas_->MeasureTextHeight(text, paintState_);
1685         } else {
1686             width = pool_->MeasureText(text, paintState_);
1687             height = pool_->MeasureTextHeight(text, paintState_);
1688         }
1689 
1690         auto retObj = JSRef<JSObject>::New();
1691         retObj->SetProperty("width", width);
1692         retObj->SetProperty("height", height);
1693         retObj->SetProperty("actualBoundingBoxLeft", SystemProperties::Px2Vp(actualBoundingBoxLeft));
1694         retObj->SetProperty("actualBoundingBoxRight", SystemProperties::Px2Vp(actualBoundingBoxRight));
1695         retObj->SetProperty("actualBoundingBoxAscent", SystemProperties::Px2Vp(actualBoundingBoxAscent));
1696         retObj->SetProperty("actualBoundingBoxDescent", SystemProperties::Px2Vp(actualBoundingBoxDescent));
1697         retObj->SetProperty("hangingBaseline", SystemProperties::Px2Vp(hangingBaseline));
1698         retObj->SetProperty("alphabeticBaseline", SystemProperties::Px2Vp(alphabeticBaseline));
1699         retObj->SetProperty("ideographicBaseline", SystemProperties::Px2Vp(ideographicBaseline));
1700         retObj->SetProperty("emHeightAscent", SystemProperties::Px2Vp(emHeightAscent));
1701         retObj->SetProperty("emHeightDescent", SystemProperties::Px2Vp(emHeightDescent));
1702         retObj->SetProperty("fontBoundingBoxAscent", SystemProperties::Px2Vp(fontBoundingBoxAscent));
1703         retObj->SetProperty("fontBoundingBoxDescent", SystemProperties::Px2Vp(fontBoundingBoxDescent));
1704         info.SetReturnValue(retObj);
1705     }
1706 }
1707 
JsFillRect(const JSCallbackInfo & info)1708 void JSCanvasRenderer::JsFillRect(const JSCallbackInfo& info)
1709 {
1710     if (info.Length() < 4) {
1711         LOGE("The arg is wrong, it is supposed to have at least 4 argument");
1712         return;
1713     }
1714 
1715     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()) {
1716         double x = 0.0;
1717         double y = 0.0;
1718         double width = 0.0;
1719         double height = 0.0;
1720         JSViewAbstract::ParseJsDouble(info[0], x);
1721         JSViewAbstract::ParseJsDouble(info[1], y);
1722         JSViewAbstract::ParseJsDouble(info[2], width);
1723         JSViewAbstract::ParseJsDouble(info[3], height);
1724         x = SystemProperties::Vp2Px(x);
1725         y = SystemProperties::Vp2Px(y);
1726         width = SystemProperties::Vp2Px(width);
1727         height = SystemProperties::Vp2Px(height);
1728 
1729         Rect rect = Rect(x, y, width, height);
1730         if (isOffscreen_) {
1731             offscreenCanvas_->FillRect(rect);
1732         } else {
1733             pool_->FillRect(rect);
1734         }
1735     }
1736 }
1737 
JsStrokeRect(const JSCallbackInfo & info)1738 void JSCanvasRenderer::JsStrokeRect(const JSCallbackInfo& info)
1739 {
1740     if (info.Length() < 4) {
1741         LOGE("The arg is wrong, it is supposed to have at least 4 argument");
1742         return;
1743     }
1744 
1745     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()) {
1746         double x = 0.0;
1747         double y = 0.0;
1748         double width = 0.0;
1749         double height = 0.0;
1750         JSViewAbstract::ParseJsDouble(info[0], x);
1751         JSViewAbstract::ParseJsDouble(info[1], y);
1752         JSViewAbstract::ParseJsDouble(info[2], width);
1753         JSViewAbstract::ParseJsDouble(info[3], height);
1754         x = SystemProperties::Vp2Px(x);
1755         y = SystemProperties::Vp2Px(y);
1756         width = SystemProperties::Vp2Px(width);
1757         height = SystemProperties::Vp2Px(height);
1758 
1759         Rect rect = Rect(x, y, width, height);
1760         if (isOffscreen_) {
1761             offscreenCanvas_->StrokeRect(rect);
1762         } else {
1763             pool_->StrokeRect(rect);
1764         }
1765     }
1766 }
1767 
JsClearRect(const JSCallbackInfo & info)1768 void JSCanvasRenderer::JsClearRect(const JSCallbackInfo& info)
1769 {
1770     if (info.Length() < 4) {
1771         LOGE("The arg is wrong, it is supposed to have at least 4 argument");
1772         return;
1773     }
1774 
1775     if (info[0]->IsNumber() && info[1]->IsNumber() && info[2]->IsNumber() && info[3]->IsNumber()) {
1776         double x = 0.0;
1777         double y = 0.0;
1778         double width = 0.0;
1779         double height = 0.0;
1780         JSViewAbstract::ParseJsDouble(info[0], x);
1781         JSViewAbstract::ParseJsDouble(info[1], y);
1782         JSViewAbstract::ParseJsDouble(info[2], width);
1783         JSViewAbstract::ParseJsDouble(info[3], height);
1784         x = SystemProperties::Vp2Px(x);
1785         y = SystemProperties::Vp2Px(y);
1786         width = SystemProperties::Vp2Px(width);
1787         height = SystemProperties::Vp2Px(height);
1788 
1789         Rect rect = Rect(x, y, width, height);
1790         if (isOffscreen_) {
1791             offscreenCanvas_->ClearRect(rect);
1792         } else {
1793             pool_->ClearRect(rect);
1794         }
1795     }
1796 }
1797 
1798 } // namespace OHOS::Ace::Framework
1799