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