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