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/canvas/js_canvas_path.h"
17 
18 #include "bridge/declarative_frontend/jsview/canvas/js_rendering_context.h"
19 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
20 
21 namespace OHOS::Ace::Framework {
22 constexpr size_t GCTHRESHOLD = 50;
23 
24 JSCanvasPath::JSCanvasPath() = default;
25 
JsPath2DSetTransform(const JSCallbackInfo & info)26 void JSCanvasPath::JsPath2DSetTransform(const JSCallbackInfo& info)
27 {
28     double scaleX = 0.0;
29     double skewX = 0.0;
30     double skewY = 0.0;
31     double scaleY = 0.0;
32     double translateX = 0.0;
33     double translateY = 0.0;
34     if (info.GetDoubleArg(0, scaleX) && info.GetDoubleArg(1, skewX) && info.GetDoubleArg(2, skewY) &&
35         info.GetDoubleArg(3, scaleY) && info.GetDoubleArg(4, translateX) && info.GetDoubleArg(5, translateY)) {
36         double density = GetDensity();
37         path2d_->SetTransform(scaleX, skewX, skewY, scaleY, translateX * density, translateY * density);
38         SetPathSize(info);
39     }
40 }
41 
42 // moveTo(x: number, y: number): void
JsPath2DMoveTo(const JSCallbackInfo & info)43 void JSCanvasPath::JsPath2DMoveTo(const JSCallbackInfo& info)
44 {
45     double x = 0.0;
46     double y = 0.0;
47     if (info.GetDoubleArg(0, x) && info.GetDoubleArg(1, y)) {
48         double density = GetDensity();
49         path2d_->MoveTo(x * density, y * density);
50         SetPathSize(info);
51     }
52 }
53 
54 // lineTo(x: number, y: number): void
JsPath2DLineTo(const JSCallbackInfo & info)55 void JSCanvasPath::JsPath2DLineTo(const JSCallbackInfo& info)
56 {
57     double x = 0.0;
58     double y = 0.0;
59     if (info.GetDoubleArg(0, x) && info.GetDoubleArg(1, y)) {
60         double density = GetDensity();
61         path2d_->LineTo(x * density, y * density);
62         SetPathSize(info);
63     }
64 }
65 
66 // arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void
JsPath2DArc(const JSCallbackInfo & info)67 void JSCanvasPath::JsPath2DArc(const JSCallbackInfo& info)
68 {
69     double x = 0.0;
70     double y = 0.0;
71     double radius = 0.0;
72     double startAngle = 0.0;
73     double endAngle = 0.0;
74     if (info.GetDoubleArg(0, x) && info.GetDoubleArg(1, y) && info.GetDoubleArg(2, radius) &&
75         info.GetDoubleArg(3, startAngle) && info.GetDoubleArg(4, endAngle)) {
76         bool anticlockwise = false;
77         info.GetBooleanArg(5, anticlockwise);
78         double density = GetDensity();
79         path2d_->Arc(x * density, y * density, radius * density, startAngle, endAngle, anticlockwise);
80         SetPathSize(info);
81     }
82 }
83 
84 // arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void
JsPath2DArcTo(const JSCallbackInfo & info)85 void JSCanvasPath::JsPath2DArcTo(const JSCallbackInfo& info)
86 {
87     double x1 = 0.0;
88     double y1 = 0.0;
89     double x2 = 0.0;
90     double y2 = 0.0;
91     double radius = 0.0;
92     if (info.GetDoubleArg(0, x1) && info.GetDoubleArg(1, y1) && info.GetDoubleArg(2, x2) && info.GetDoubleArg(3, y2) &&
93         info.GetDoubleArg(4, radius)) {
94         double density = GetDensity();
95         path2d_->ArcTo(x1 * density, y1 * density, x2 * density, y2 * density, radius * density);
96         SetPathSize(info);
97     }
98 }
99 
100 // quadraticCurveTo(cpx: number, cpy: number, x: number ,y: number): void
JsPath2DQuadraticCurveTo(const JSCallbackInfo & info)101 void JSCanvasPath::JsPath2DQuadraticCurveTo(const JSCallbackInfo& info)
102 {
103     double cpx = 0.0;
104     double cpy = 0.0;
105     double x = 0.0;
106     double y = 0.0;
107     if (info.GetDoubleArg(0, cpx) && info.GetDoubleArg(1, cpy) && info.GetDoubleArg(2, x) && info.GetDoubleArg(3, y)) {
108         double density = GetDensity();
109         path2d_->QuadraticCurveTo(cpx * density, cpy * density, x * density, y * density);
110         SetPathSize(info);
111     }
112 }
113 
114 // bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void
JsPath2DBezierCurveTo(const JSCallbackInfo & info)115 void JSCanvasPath::JsPath2DBezierCurveTo(const JSCallbackInfo& info)
116 {
117     double cp1x = 0.0;
118     double cp1y = 0.0;
119     double cp2x = 0.0;
120     double cp2y = 0.0;
121     double x = 0.0;
122     double y = 0.0;
123     if (info.GetDoubleArg(0, cp1x) && info.GetDoubleArg(1, cp1y) && info.GetDoubleArg(2, cp2x) &&
124         info.GetDoubleArg(3, cp2y) && info.GetDoubleArg(4, x) && info.GetDoubleArg(5, y)) {
125         double density = GetDensity();
126         path2d_->BezierCurveTo(
127             cp1x * density, cp1y * density, cp2x * density, cp2y * density, x * density, y * density);
128         SetPathSize(info);
129     }
130 }
131 
132 // ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number,
133 //         endAngle: number, counterclockwise?: boolean): void
JsPath2DEllipse(const JSCallbackInfo & info)134 void JSCanvasPath::JsPath2DEllipse(const JSCallbackInfo& info)
135 {
136     double x = 0.0;
137     double y = 0.0;
138     double radiusX = 0.0;
139     double radiusY = 0.0;
140     double rotation = 0.0;
141     double startAngle = 0.0;
142     double endAngle = 0.0;
143     if (info.GetDoubleArg(0, x) && info.GetDoubleArg(1, y) && info.GetDoubleArg(2, radiusX) &&
144         info.GetDoubleArg(3, radiusY) && info.GetDoubleArg(4, rotation) && info.GetDoubleArg(5, startAngle) &&
145         info.GetDoubleArg(6, endAngle)) {
146         bool anticlockwise = false;
147         info.GetBooleanArg(7, anticlockwise);
148         double density = GetDensity();
149         path2d_->Ellipse(x * density, y * density, radiusX * density, radiusY * density, rotation,
150             startAngle, endAngle, anticlockwise);
151         SetPathSize(info);
152     }
153 }
154 
155 // rect(x: number, y: number, w: number, h: number): void
JsPath2DRect(const JSCallbackInfo & info)156 void JSCanvasPath::JsPath2DRect(const JSCallbackInfo& info)
157 {
158     double x = 0.0;
159     double y = 0.0;
160     double width = 0.0;
161     double height = 0.0;
162     if (info.GetDoubleArg(0, x) && info.GetDoubleArg(1, y) && info.GetDoubleArg(2, width) &&
163         info.GetDoubleArg(3, height)) {
164         double density = GetDensity();
165         path2d_->Rect(x * density, y * density, width * density, height * density);
166         SetPathSize(info);
167     }
168 }
169 
170 // closePath(): void
JsPath2DClosePath(const JSCallbackInfo & info)171 void JSCanvasPath::JsPath2DClosePath(const JSCallbackInfo& info)
172 {
173     path2d_->ClosePath();
174     SetPathSize(info);
175 }
176 
SetPathSize(const JSCallbackInfo & info)177 void JSCanvasPath::SetPathSize(const JSCallbackInfo& info)
178 {
179     CHECK_NULL_VOID(path2d_);
180     const std::vector<std::pair<PathCmd, PathArgs>> caches = path2d_->GetCaches();
181     size_t pathSize = caches.size();
182     if (pathSize - lastPathSize_ > GCTHRESHOLD) {
183         EcmaVM* vm = info.GetVm();
184         CHECK_NULL_VOID(vm);
185         panda::CopyableGlobal<ObjectRef> pathCmdObj = panda::CopyableGlobal<ObjectRef>(pathCmdObj_);
186         if (!pathCmdObj.IsEmpty()) {
187             pathCmdObj->SetNativePointerField(
188                 vm, 0, nullptr, &JSCanvasPath::DestructorInterceptor, nullptr,
189                 (pathSize - lastPathSize_) * sizeof(std::pair<PathCmd, PathArgs>));
190             lastPathSize_ = pathSize;
191         }
192     }
193 }
194 } // namespace OHOS::Ace::Framework
195