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