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