1 /*
2 * Copyright (c) 2022-2023 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 "base/utils/utils.h"
17 #include "bridge/declarative_frontend/engine/bindings.h"
18 #include "bridge/declarative_frontend/jsview/js_offscreen_canvas.h"
19
20 namespace OHOS::Ace::Framework {
JSBind(BindingTarget globalObj)21 void JSOffscreenCanvas::JSBind(BindingTarget globalObj)
22 {
23 JSClass<JSOffscreenCanvas>::Declare("OffscreenCanvas");
24 JSClass<JSOffscreenCanvas>::CustomProperty("width", &JSOffscreenCanvas::JsGetWidth,
25 &JSOffscreenCanvas::JsSetWidth);
26 JSClass<JSOffscreenCanvas>::CustomProperty("height", &JSOffscreenCanvas::JsGetHeight,
27 &JSOffscreenCanvas::JsSetHeight);
28 JSClass<JSOffscreenCanvas>::CustomMethod("transferToImageBitmap",
29 &JSOffscreenCanvas::JsTransferToImageBitmap);
30 JSClass<JSOffscreenCanvas>::CustomMethod("getContext", &JSOffscreenCanvas::JsGetContext);
31
32 JSClass<JSOffscreenCanvas>::CustomMethod("createRadialGradient",
33 &JSOffscreenCanvas::JsCreateRadialGradient);
34 JSClass<JSOffscreenCanvas>::CustomMethod("fillRect", &JSOffscreenCanvas::JsFillRect);
35 JSClass<JSOffscreenCanvas>::CustomMethod("strokeRect", &JSOffscreenCanvas::JsStrokeRect);
36 JSClass<JSOffscreenCanvas>::CustomMethod("clearRect", &JSOffscreenCanvas::JsClearRect);
37 JSClass<JSOffscreenCanvas>::CustomMethod("createLinearGradient",
38 &JSOffscreenCanvas::JsCreateLinearGradient);
39 JSClass<JSOffscreenCanvas>::CustomMethod("fillText", &JSOffscreenCanvas::JsFillText);
40 JSClass<JSOffscreenCanvas>::CustomMethod("strokeText", &JSOffscreenCanvas::JsStrokeText);
41 JSClass<JSOffscreenCanvas>::CustomMethod("measureText", &JSOffscreenCanvas::JsMeasureText);
42 JSClass<JSOffscreenCanvas>::CustomMethod("moveTo", &JSOffscreenCanvas::JsMoveTo);
43 JSClass<JSOffscreenCanvas>::CustomMethod("lineTo", &JSOffscreenCanvas::JsLineTo);
44 JSClass<JSOffscreenCanvas>::CustomMethod("bezierCurveTo", &JSOffscreenCanvas::JsBezierCurveTo);
45 JSClass<JSOffscreenCanvas>::CustomMethod("quadraticCurveTo", &JSOffscreenCanvas::JsQuadraticCurveTo);
46 JSClass<JSOffscreenCanvas>::CustomMethod("arcTo", &JSOffscreenCanvas::JsArcTo);
47 JSClass<JSOffscreenCanvas>::CustomMethod("arc", &JSOffscreenCanvas::JsArc);
48 JSClass<JSOffscreenCanvas>::CustomMethod("ellipse", &JSOffscreenCanvas::JsEllipse);
49 JSClass<JSOffscreenCanvas>::CustomMethod("fill", &JSOffscreenCanvas::JsFill);
50 JSClass<JSOffscreenCanvas>::CustomMethod("stroke", &JSOffscreenCanvas::JsStroke);
51 JSClass<JSOffscreenCanvas>::CustomMethod("clip", &JSOffscreenCanvas::JsClip);
52 JSClass<JSOffscreenCanvas>::CustomMethod("rect", &JSOffscreenCanvas::JsRect);
53 JSClass<JSOffscreenCanvas>::CustomMethod("beginPath", &JSOffscreenCanvas::JsBeginPath);
54 JSClass<JSOffscreenCanvas>::CustomMethod("closePath", &JSOffscreenCanvas::JsClosePath);
55 JSClass<JSOffscreenCanvas>::CustomMethod("restore", &JSOffscreenCanvas::JsRestore);
56 JSClass<JSOffscreenCanvas>::CustomMethod("save", &JSOffscreenCanvas::JsSave);
57 JSClass<JSOffscreenCanvas>::CustomMethod("rotate", &JSOffscreenCanvas::JsRotate);
58 JSClass<JSOffscreenCanvas>::CustomMethod("scale", &JSOffscreenCanvas::JsScale);
59 JSClass<JSOffscreenCanvas>::CustomMethod("getTransform", &JSOffscreenCanvas::JsGetTransform);
60 JSClass<JSOffscreenCanvas>::CustomMethod("setTransform", &JSOffscreenCanvas::JsSetTransform);
61 JSClass<JSOffscreenCanvas>::CustomMethod("resetTransform", &JSOffscreenCanvas::JsResetTransform);
62 JSClass<JSOffscreenCanvas>::CustomMethod("transform", &JSOffscreenCanvas::JsTransform);
63 JSClass<JSOffscreenCanvas>::CustomMethod("translate", &JSOffscreenCanvas::JsTranslate);
64 JSClass<JSOffscreenCanvas>::CustomMethod("setLineDash", &JSOffscreenCanvas::JsSetLineDash);
65 JSClass<JSOffscreenCanvas>::CustomMethod("getLineDash", &JSOffscreenCanvas::JsGetLineDash);
66 JSClass<JSOffscreenCanvas>::CustomMethod("drawImage", &JSOffscreenCanvas::JsDrawImage);
67 JSClass<JSOffscreenCanvas>::CustomMethod("createPattern", &JSOffscreenCanvas::JsCreatePattern);
68 JSClass<JSOffscreenCanvas>::CustomMethod("createImageData", &JSOffscreenCanvas::JsCreateImageData);
69 JSClass<JSOffscreenCanvas>::CustomMethod("putImageData", &JSOffscreenCanvas::JsPutImageData);
70 JSClass<JSOffscreenCanvas>::CustomMethod("getImageData", &JSOffscreenCanvas::JsGetImageData);
71 JSClass<JSOffscreenCanvas>::CustomMethod("getJsonData", &JSOffscreenCanvas::JsGetJsonData);
72 JSClass<JSOffscreenCanvas>::CustomMethod("getPixelMap", &JSOffscreenCanvas::JsGetPixelMap);
73 JSClass<JSOffscreenCanvas>::CustomMethod("setPixelMap", &JSOffscreenCanvas::JsSetPixelMap);
74 JSClass<JSOffscreenCanvas>::CustomMethod("createConicGradient", &JSOffscreenCanvas::JsCreateConicGradient);
75 JSClass<JSOffscreenCanvas>::CustomMethod("transferFromImageBitmap", &JSOffscreenCanvas::JSTransferFromImageBitmap);
76 JSClass<JSOffscreenCanvas>::CustomProperty("filter", &JSOffscreenCanvas::JsGetFilter,
77 &JSOffscreenCanvas::JsSetFilter);
78 JSClass<JSOffscreenCanvas>::CustomProperty("direction", &JSOffscreenCanvas::JsGetDirection,
79 &JSOffscreenCanvas::JsSetDirection);
80 JSClass<JSOffscreenCanvas>::CustomProperty("fillStyle", &JSOffscreenCanvas::JsGetFillStyle,
81 &JSOffscreenCanvas::JsSetFillStyle);
82 JSClass<JSOffscreenCanvas>::CustomProperty("strokeStyle", &JSOffscreenCanvas::JsGetStrokeStyle,
83 &JSOffscreenCanvas::JsSetStrokeStyle);
84 JSClass<JSOffscreenCanvas>::CustomProperty("lineCap", &JSOffscreenCanvas::JsGetLineCap,
85 &JSOffscreenCanvas::JsSetLineCap);
86 JSClass<JSOffscreenCanvas>::CustomProperty("lineJoin", &JSOffscreenCanvas::JsGetLineJoin,
87 &JSOffscreenCanvas::JsSetLineJoin);
88 JSClass<JSOffscreenCanvas>::CustomProperty("miterLimit", &JSOffscreenCanvas::JsGetMiterLimit,
89 &JSOffscreenCanvas::JsSetMiterLimit);
90 JSClass<JSOffscreenCanvas>::CustomProperty("lineWidth", &JSOffscreenCanvas::JsGetLineWidth,
91 &JSOffscreenCanvas::JsSetLineWidth);
92 JSClass<JSOffscreenCanvas>::CustomProperty("font", &JSOffscreenCanvas::JsGetFont,
93 &JSOffscreenCanvas::JsSetFont);
94 JSClass<JSOffscreenCanvas>::CustomProperty("textAlign", &JSOffscreenCanvas::JsGetTextAlign,
95 &JSOffscreenCanvas::JsSetTextAlign);
96 JSClass<JSOffscreenCanvas>::CustomProperty("textBaseline", &JSOffscreenCanvas::JsGetTextBaseline,
97 &JSOffscreenCanvas::JsSetTextBaseline);
98 JSClass<JSOffscreenCanvas>::CustomProperty("globalAlpha", &JSOffscreenCanvas::JsGetGlobalAlpha,
99 &JSOffscreenCanvas::JsSetGlobalAlpha);
100 JSClass<JSOffscreenCanvas>::CustomProperty("globalCompositeOperation",
101 &JSOffscreenCanvas::JsGetGlobalCompositeOperation, &JSOffscreenCanvas::JsSetGlobalCompositeOperation);
102 JSClass<JSOffscreenCanvas>::CustomProperty("lineDashOffset", &JSOffscreenCanvas::JsGetLineDashOffset,
103 &JSOffscreenCanvas::JsSetLineDashOffset);
104 JSClass<JSOffscreenCanvas>::CustomProperty("shadowBlur", &JSOffscreenCanvas::JsGetShadowBlur,
105 &JSOffscreenCanvas::JsSetShadowBlur);
106 JSClass<JSOffscreenCanvas>::CustomProperty("shadowColor", &JSOffscreenCanvas::JsGetShadowColor,
107 &JSOffscreenCanvas::JsSetShadowColor);
108 JSClass<JSOffscreenCanvas>::CustomProperty("shadowOffsetX", &JSOffscreenCanvas::JsGetShadowOffsetX,
109 &JSOffscreenCanvas::JsSetShadowOffsetX);
110 JSClass<JSOffscreenCanvas>::CustomProperty("shadowOffsetY", &JSOffscreenCanvas::JsGetShadowOffsetY,
111 &JSOffscreenCanvas::JsSetShadowOffsetY);
112 JSClass<JSOffscreenCanvas>::CustomProperty("imageSmoothingEnabled",
113 &JSOffscreenCanvas::JsGetImageSmoothingEnabled, &JSOffscreenCanvas::JsSetImageSmoothingEnabled);
114 JSClass<JSOffscreenCanvas>::CustomProperty("imageSmoothingQuality",
115 &JSOffscreenCanvas::JsGetImageSmoothingQuality, &JSOffscreenCanvas::JsSetImageSmoothingQuality);
116 JSClass<JSOffscreenCanvas>::Bind(globalObj, JSOffscreenCanvas::Constructor, JSOffscreenCanvas::Destructor);
117 }
118
Constructor(const JSCallbackInfo & args)119 void JSOffscreenCanvas::Constructor(const JSCallbackInfo& args)
120 {
121 if (args.Length() < 2) {
122 LOGE("The arg is wrong, it is supposed to have at least 2 argument");
123 return;
124 }
125 if (Container::IsCurrentUseNewPipeline() && args[0]->IsNumber() && args[1]->IsNumber()) {
126 auto offscreenCanvas = Referenced::MakeRefPtr<JSOffscreenCanvas>();
127 CHECK_NULL_VOID(offscreenCanvas);
128 offscreenCanvas->IncRefCount();
129 double fWidth = 0.0;
130 double fHeight = 0.0;
131 if (JSViewAbstract::ParseJsDouble(args[0], fWidth)) {
132 fWidth = SystemProperties::Vp2Px(fWidth);
133 offscreenCanvas->SetWidth(round(fWidth));
134 }
135 if (JSViewAbstract::ParseJsDouble(args[1], fHeight)) {
136 fHeight = SystemProperties::Vp2Px(fHeight);
137 offscreenCanvas->SetHeight(round(fHeight));
138 }
139 args.SetReturnValue(Referenced::RawPtr(offscreenCanvas));
140 }
141 }
142
Destructor(JSOffscreenCanvas * context)143 void JSOffscreenCanvas::Destructor(JSOffscreenCanvas* context)
144 {
145 if (context != nullptr) {
146 context->DecRefCount();
147 } else {
148 LOGE("context is null");
149 return;
150 }
151 }
152
JsGetWidth(const JSCallbackInfo & info)153 void JSOffscreenCanvas::JsGetWidth(const JSCallbackInfo& info)
154 {
155 double fWidth = SystemProperties::Px2Vp(GetWidth());
156 auto returnValue = JSVal(ToJSValue(fWidth));
157 auto returnPtr = JSRef<JSVal>::Make(returnValue);
158 info.SetReturnValue(returnPtr);
159 }
160
JsGetHeight(const JSCallbackInfo & info)161 void JSOffscreenCanvas::JsGetHeight(const JSCallbackInfo& info)
162 {
163 double fHeight = SystemProperties::Px2Vp(GetHeight());
164 auto returnValue = JSVal(ToJSValue(fHeight));
165 auto returnPtr = JSRef<JSVal>::Make(returnValue);
166 info.SetReturnValue(returnPtr);
167 }
168
JsSetWidth(const JSCallbackInfo & info)169 void JSOffscreenCanvas::JsSetWidth(const JSCallbackInfo& info)
170 {
171 if (info.Length() != 1) {
172 LOGE("The arg is wrong, it is supposed to have 1 argument");
173 return;
174 }
175 if (info[0]->IsUndefined() || info[0]->IsNull()) {
176 return;
177 }
178 double width = 0.0;
179 if (JSViewAbstract::ParseJsDouble(info[0], width)) {
180 width_ = SystemProperties::Vp2Px(width);
181 } else {
182 return;
183 }
184
185 if (contextType_ == ContextType::CONTEXT_2D) {
186 CreateContext2d(width_, GetHeight());
187 }
188 return;
189 }
190
JsSetHeight(const JSCallbackInfo & info)191 void JSOffscreenCanvas::JsSetHeight(const JSCallbackInfo& info)
192 {
193 if (info.Length() != 1) {
194 LOGE("The arg is wrong, it is supposed to have 1 argument");
195 return;
196 }
197
198 if (info[0]->IsUndefined() || info[0]->IsNull()) {
199 return;
200 }
201 double height = 0.0;
202 if (JSViewAbstract::ParseJsDouble(info[0], height)) {
203 height_ = SystemProperties::Vp2Px(height);
204 } else {
205 return;
206 }
207
208 if (contextType_ == ContextType::CONTEXT_2D) {
209 CreateContext2d(GetWidth(), height_);
210 }
211 return;
212 }
213
JsTransferToImageBitmap(const JSCallbackInfo & info)214 void JSOffscreenCanvas::JsTransferToImageBitmap(const JSCallbackInfo& info)
215 {
216 if (Container::IsCurrentUseNewPipeline()) {
217 CHECK_NULL_VOID(offscreenCanvasContext_);
218 CHECK_NULL_VOID(offscreenCanvasPattern_);
219 auto final_height = static_cast<uint32_t>(GetHeight());
220 auto final_width = static_cast<uint32_t>(GetWidth());
221 JSRef<JSObject> renderImage = JSRef<JSObject>::New();
222 renderImage->SetProperty("__type", "ImageBitmap");
223 renderImage->SetProperty("__id", offscreenCanvasContext_->GetId());
224 renderImage->SetProperty("height", final_height);
225 renderImage->SetProperty("width", final_width);
226 info.SetReturnValue(renderImage);
227 }
228 }
229
JsGetContext(const JSCallbackInfo & info)230 void JSOffscreenCanvas::JsGetContext(const JSCallbackInfo& info)
231 {
232 if (info.Length() < 1 || info.Length() > 2) {
233 LOGE("The arg is wrong, it is supposed to have at least 1 argument and at most 2 arguments");
234 return;
235 }
236 if (info[0]->IsUndefined() || info[0]->IsNull()) {
237 LOGE("Invalid arguments.");
238 return;
239 }
240 if (!Container::IsCurrentUseNewPipeline()) {
241 return;
242 }
243
244 if (info[0]->IsString()) {
245 std::string ruleStr;
246 JSViewAbstract::ParseJsString(info[0], ruleStr);
247 if (ruleStr == "2d") {
248 contextType_ = ContextType::CONTEXT_2D;
249 auto contextObj = CreateContext2d(GetWidth(), GetHeight());
250 if (contextObj->IsEmpty()) {
251 return;
252 }
253 JSRef<JSVal> isSucceed = contextObj->GetProperty("__isSucceed");
254 if (isSucceed->IsBoolean() && !isSucceed->ToBoolean()) {
255 return;
256 }
257 if (info[1]->IsObject()) {
258 offscreenCanvasSettings_ = JSRef<JSObject>::Cast(info[1])->Unwrap<JSRenderingContextSettings>();
259 CHECK_NULL_VOID(offscreenCanvasSettings_);
260 bool anti = offscreenCanvasSettings_->GetAntialias();
261 offscreenCanvasContext_->SetAnti(anti);
262 offscreenCanvasContext_->SetAntiAlias();
263 }
264 info.SetReturnValue(contextObj);
265 }
266 }
267 }
268
CreateContext2d(double width,double height)269 JSRef<JSObject> JSOffscreenCanvas::CreateContext2d(double width, double height)
270 {
271 JSRef<JSObject> contextObj = JSClass<JSOffscreenRenderingContext>::NewInstance();
272 if (contextObj->IsEmpty()) {
273 return contextObj;
274 }
275 contextObj->SetProperty("__type", "OffscreenCanvasRenderingContext2D");
276 offscreenCanvasContext_ = Referenced::Claim(contextObj->Unwrap<JSOffscreenRenderingContext>());
277 offscreenCanvasPattern_ = AceType::MakeRefPtr<NG::OffscreenCanvasPattern>(
278 static_cast<int32_t>(width), static_cast<int32_t>(height));
279 CHECK_NULL_RETURN(offscreenCanvasPattern_, contextObj);
280 if (!offscreenCanvasPattern_->IsSucceed()) {
281 contextObj->SetProperty("__isSucceed", false);
282 return contextObj;
283 }
284 contextObj->SetProperty("__isSucceed", true);
285 offscreenCanvasContext_->SetOffscreenPattern(offscreenCanvasPattern_);
286 offscreenCanvasContext_->AddOffscreenCanvasPattern(offscreenCanvasPattern_);
287 CHECK_NULL_RETURN(offscreenCanvasSettings_, contextObj);
288 bool anti = offscreenCanvasSettings_->GetAntialias();
289 offscreenCanvasContext_->SetAnti(anti);
290 offscreenCanvasContext_->SetAntiAlias();
291 return contextObj;
292 }
293 } // namespace OHOS::Ace::Framework
294