1 /*
2 * Copyright (c) 2024-2025 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 "js_path.h"
17
18 #include "native_value.h"
19
20 #include "js_drawing_utils.h"
21 #include "matrix_napi/js_matrix.h"
22 #include "path_iterator_napi/js_path_iterator.h"
23 #include "roundRect_napi/js_roundrect.h"
24 #include "utils/performanceCaculate.h"
25
26 #include "matrix_napi/js_matrix.h"
27
28 namespace OHOS::Rosen {
29 namespace Drawing {
30 thread_local napi_ref JsPath::constructor_ = nullptr;
31 const std::string CLASS_NAME = "Path";
32
33 static const napi_property_descriptor g_properties[] = {
34 DECLARE_NAPI_FUNCTION("moveTo", JsPath::MoveTo),
35 DECLARE_NAPI_FUNCTION("lineTo", JsPath::LineTo),
36 DECLARE_NAPI_FUNCTION("arcTo", JsPath::ArcTo),
37 DECLARE_NAPI_FUNCTION("quadTo", JsPath::QuadTo),
38 DECLARE_NAPI_FUNCTION("conicTo", JsPath::ConicTo),
39 DECLARE_NAPI_FUNCTION("cubicTo", JsPath::CubicTo),
40 DECLARE_NAPI_FUNCTION("rMoveTo", JsPath::RMoveTo),
41 DECLARE_NAPI_FUNCTION("rLineTo", JsPath::RLineTo),
42 DECLARE_NAPI_FUNCTION("rQuadTo", JsPath::RQuadTo),
43 DECLARE_NAPI_FUNCTION("rConicTo", JsPath::RConicTo),
44 DECLARE_NAPI_FUNCTION("rCubicTo", JsPath::RCubicTo),
45 DECLARE_NAPI_FUNCTION("addPolygon", JsPath::AddPolygon),
46 DECLARE_NAPI_FUNCTION("addOval", JsPath::AddOval),
47 DECLARE_NAPI_FUNCTION("addCircle", JsPath::AddCircle),
48 DECLARE_NAPI_FUNCTION("addArc", JsPath::AddArc),
49 DECLARE_NAPI_FUNCTION("addRect", JsPath::AddRect),
50 DECLARE_NAPI_FUNCTION("addRoundRect", JsPath::AddRoundRect),
51 DECLARE_NAPI_FUNCTION("addPath", JsPath::AddPath),
52 DECLARE_NAPI_FUNCTION("transform", JsPath::Transform),
53 DECLARE_NAPI_FUNCTION("contains", JsPath::Contains),
54 DECLARE_NAPI_FUNCTION("set", JsPath::Set),
55 DECLARE_NAPI_FUNCTION("setFillType", JsPath::SetFillType),
56 DECLARE_NAPI_FUNCTION("setLastPoint", JsPath::SetLastPoint),
57 DECLARE_NAPI_FUNCTION("getBounds", JsPath::GetBounds),
58 DECLARE_NAPI_FUNCTION("close", JsPath::Close),
59 DECLARE_NAPI_FUNCTION("offset", JsPath::Offset),
60 DECLARE_NAPI_FUNCTION("rewind", JsPath::ReWind),
61 DECLARE_NAPI_FUNCTION("reset", JsPath::Reset),
62 DECLARE_NAPI_FUNCTION("op", JsPath::Op),
63 DECLARE_NAPI_FUNCTION("getLength", JsPath::GetLength),
64 DECLARE_NAPI_FUNCTION("getPositionAndTangent", JsPath::GetPositionAndTangent),
65 DECLARE_NAPI_FUNCTION("getFillType", JsPath::GetFillType),
66 DECLARE_NAPI_FUNCTION("getSegment", JsPath::GetSegment),
67 DECLARE_NAPI_FUNCTION("getMatrix", JsPath::GetMatrix),
68 DECLARE_NAPI_FUNCTION("buildFromSvgString", JsPath::BuildFromSvgString),
69 DECLARE_NAPI_FUNCTION("isClosed", JsPath::IsClosed),
70 DECLARE_NAPI_FUNCTION("isEmpty", JsPath::IsEmpty),
71 DECLARE_NAPI_FUNCTION("isRect", JsPath::IsRect),
72 DECLARE_NAPI_FUNCTION("getPathIterator", JsPath::GetPathIterator),
73 DECLARE_NAPI_FUNCTION("approximate", JsPath::Approximate),
74 DECLARE_NAPI_FUNCTION("interpolate", JsPath::Interpolate),
75 DECLARE_NAPI_FUNCTION("isInterpolate", JsPath::IsInterpolate),
76 };
77
Init(napi_env env,napi_value exportObj)78 napi_value JsPath::Init(napi_env env, napi_value exportObj)
79 {
80 napi_value constructor = nullptr;
81 napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
82 sizeof(g_properties) / sizeof(g_properties[0]), g_properties, &constructor);
83 if (status != napi_ok) {
84 ROSEN_LOGE("Failed to define Path class");
85 return nullptr;
86 }
87
88 status = napi_create_reference(env, constructor, 1, &constructor_);
89 if (status != napi_ok) {
90 ROSEN_LOGE("Failed to create reference of constructor");
91 return nullptr;
92 }
93
94 status = napi_set_named_property(env, exportObj, CLASS_NAME.c_str(), constructor);
95 if (status != napi_ok) {
96 ROSEN_LOGE("Failed to set constructor");
97 return nullptr;
98 }
99
100 return exportObj;
101 }
102
Constructor(napi_env env,napi_callback_info info)103 napi_value JsPath::Constructor(napi_env env, napi_callback_info info)
104 {
105 size_t argc = ARGC_ONE;
106 napi_value argv[ARGC_ONE] = {nullptr};
107 napi_value jsThis = nullptr;
108 JsPath* jsPath = nullptr;
109 napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
110 if (status != napi_ok) {
111 ROSEN_LOGE("Path::Constructor Failed to napi_get_cb_info");
112 return nullptr;
113 }
114 if (argc == ARGC_ZERO) {
115 Path* path = new Path();
116 jsPath = new JsPath(path);
117 } else if (argc == ARGC_ONE) {
118 napi_valuetype valueType = napi_undefined;
119 if (argv[0] == nullptr || napi_typeof(env, argv[0], &valueType) != napi_ok || valueType != napi_object) {
120 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
121 "JsPath::Constructor Argv[0] is invalid");
122 }
123 JsPath* path = nullptr;
124 GET_UNWRAP_PARAM(ARGC_ZERO, path);
125 Path* p = new Path(*path->GetPath());
126 jsPath = new JsPath(p);
127 } else {
128 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect number of parameters.");
129 }
130 if (!jsPath) {
131 ROSEN_LOGE("Failed to create JsPath");
132 return nullptr;
133 }
134 status = napi_wrap(env, jsThis, jsPath,
135 JsPath::Destructor, nullptr, nullptr);
136 if (status != napi_ok) {
137 delete jsPath;
138 ROSEN_LOGE("JsPath::Constructor Failed to wrap native instance");
139 return nullptr;
140 }
141 return jsThis;
142 }
143
Destructor(napi_env env,void * nativeObject,void * finalize)144 void JsPath::Destructor(napi_env env, void *nativeObject, void *finalize)
145 {
146 (void)finalize;
147 if (nativeObject != nullptr) {
148 JsPath *napi = reinterpret_cast<JsPath *>(nativeObject);
149 delete napi;
150 }
151 }
152
CreateJsPath(napi_env env,Path * path)153 napi_value JsPath::CreateJsPath(napi_env env, Path* path)
154 {
155 napi_value constructor = nullptr;
156 napi_status status = napi_get_reference_value(env, constructor_, &constructor);
157 if (status != napi_ok) {
158 delete path;
159 ROSEN_LOGE("JsPath::CreateJsPath failed to get reference value!");
160 return nullptr;
161 }
162 napi_value result = nullptr;
163 napi_create_object(env, &result);
164 if (result == nullptr) {
165 delete path;
166 ROSEN_LOGE("JsPath::CreateJsPath create object failed!");
167 return nullptr;
168 }
169 JsPath* jsPath = new JsPath(path);
170 status = napi_wrap(env, result, jsPath, JsPath::Destructor, nullptr, nullptr);
171 if (status != napi_ok) {
172 delete jsPath;
173 ROSEN_LOGE("JsPath::CreateJsPath failed to wrap native instance");
174 return nullptr;
175 }
176 napi_define_properties(env, result, sizeof(g_properties) / sizeof(g_properties[0]), g_properties);
177 return result;
178 }
179
~JsPath()180 JsPath::~JsPath()
181 {
182 if (m_path != nullptr) {
183 delete m_path;
184 m_path = nullptr;
185 }
186 }
187
MoveTo(napi_env env,napi_callback_info info)188 napi_value JsPath::MoveTo(napi_env env, napi_callback_info info)
189 {
190 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
191 return (me != nullptr) ? me->OnMoveTo(env, info) : nullptr;
192 }
193
LineTo(napi_env env,napi_callback_info info)194 napi_value JsPath::LineTo(napi_env env, napi_callback_info info)
195 {
196 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
197 return (me != nullptr) ? me->OnLineTo(env, info) : nullptr;
198 }
199
ArcTo(napi_env env,napi_callback_info info)200 napi_value JsPath::ArcTo(napi_env env, napi_callback_info info)
201 {
202 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
203 return (me != nullptr) ? me->OnArcTo(env, info) : nullptr;
204 }
205
QuadTo(napi_env env,napi_callback_info info)206 napi_value JsPath::QuadTo(napi_env env, napi_callback_info info)
207 {
208 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
209 return (me != nullptr) ? me->OnQuadTo(env, info) : nullptr;
210 }
211
ConicTo(napi_env env,napi_callback_info info)212 napi_value JsPath::ConicTo(napi_env env, napi_callback_info info)
213 {
214 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
215 return (me != nullptr) ? me->OnConicTo(env, info) : nullptr;
216 }
217
CubicTo(napi_env env,napi_callback_info info)218 napi_value JsPath::CubicTo(napi_env env, napi_callback_info info)
219 {
220 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
221 return (me != nullptr) ? me->OnCubicTo(env, info) : nullptr;
222 }
223
RMoveTo(napi_env env,napi_callback_info info)224 napi_value JsPath::RMoveTo(napi_env env, napi_callback_info info)
225 {
226 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
227 return (me != nullptr) ? me->OnRMoveTo(env, info) : nullptr;
228 }
229
RLineTo(napi_env env,napi_callback_info info)230 napi_value JsPath::RLineTo(napi_env env, napi_callback_info info)
231 {
232 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
233 return (me != nullptr) ? me->OnRLineTo(env, info) : nullptr;
234 }
235
RQuadTo(napi_env env,napi_callback_info info)236 napi_value JsPath::RQuadTo(napi_env env, napi_callback_info info)
237 {
238 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
239 return (me != nullptr) ? me->OnRQuadTo(env, info) : nullptr;
240 }
241
RConicTo(napi_env env,napi_callback_info info)242 napi_value JsPath::RConicTo(napi_env env, napi_callback_info info)
243 {
244 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
245 return (me != nullptr) ? me->OnRConicTo(env, info) : nullptr;
246 }
247
RCubicTo(napi_env env,napi_callback_info info)248 napi_value JsPath::RCubicTo(napi_env env, napi_callback_info info)
249 {
250 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
251 return (me != nullptr) ? me->OnRCubicTo(env, info) : nullptr;
252 }
253
AddPolygon(napi_env env,napi_callback_info info)254 napi_value JsPath::AddPolygon(napi_env env, napi_callback_info info)
255 {
256 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
257 return (me != nullptr) ? me->OnAddPolygon(env, info) : nullptr;
258 }
259
AddOval(napi_env env,napi_callback_info info)260 napi_value JsPath::AddOval(napi_env env, napi_callback_info info)
261 {
262 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
263 return (me != nullptr) ? me->OnAddOval(env, info) : nullptr;
264 }
265
AddCircle(napi_env env,napi_callback_info info)266 napi_value JsPath::AddCircle(napi_env env, napi_callback_info info)
267 {
268 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
269 return (me != nullptr) ? me->OnAddCircle(env, info) : nullptr;
270 }
271
AddArc(napi_env env,napi_callback_info info)272 napi_value JsPath::AddArc(napi_env env, napi_callback_info info)
273 {
274 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
275 return (me != nullptr) ? me->OnAddArc(env, info) : nullptr;
276 }
277
AddRect(napi_env env,napi_callback_info info)278 napi_value JsPath::AddRect(napi_env env, napi_callback_info info)
279 {
280 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
281 return (me != nullptr) ? me->OnAddRect(env, info) : nullptr;
282 }
283
AddRoundRect(napi_env env,napi_callback_info info)284 napi_value JsPath::AddRoundRect(napi_env env, napi_callback_info info)
285 {
286 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
287 return (me != nullptr) ? me->OnAddRoundRect(env, info) : nullptr;
288 }
289
AddPath(napi_env env,napi_callback_info info)290 napi_value JsPath::AddPath(napi_env env, napi_callback_info info)
291 {
292 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
293 return (me != nullptr) ? me->OnAddPath(env, info) : nullptr;
294 }
295
Transform(napi_env env,napi_callback_info info)296 napi_value JsPath::Transform(napi_env env, napi_callback_info info)
297 {
298 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
299 return (me != nullptr) ? me->OnTransform(env, info) : nullptr;
300 }
301
Contains(napi_env env,napi_callback_info info)302 napi_value JsPath::Contains(napi_env env, napi_callback_info info)
303 {
304 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
305 return (me != nullptr) ? me->OnContains(env, info) : nullptr;
306 }
307
SetFillType(napi_env env,napi_callback_info info)308 napi_value JsPath::SetFillType(napi_env env, napi_callback_info info)
309 {
310 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
311 return (me != nullptr) ? me->OnSetFillType(env, info) : nullptr;
312 }
313
GetBounds(napi_env env,napi_callback_info info)314 napi_value JsPath::GetBounds(napi_env env, napi_callback_info info)
315 {
316 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
317 return (me != nullptr) ? me->OnGetBounds(env, info) : nullptr;
318 }
319
Close(napi_env env,napi_callback_info info)320 napi_value JsPath::Close(napi_env env, napi_callback_info info)
321 {
322 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
323 return (me != nullptr) ? me->OnClose(env, info) : nullptr;
324 }
325
Offset(napi_env env,napi_callback_info info)326 napi_value JsPath::Offset(napi_env env, napi_callback_info info)
327 {
328 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
329 return (me != nullptr) ? me->OnOffset(env, info) : nullptr;
330 }
331
Reset(napi_env env,napi_callback_info info)332 napi_value JsPath::Reset(napi_env env, napi_callback_info info)
333 {
334 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
335 return (me != nullptr) ? me->OnReset(env, info) : nullptr;
336 }
337
GetLength(napi_env env,napi_callback_info info)338 napi_value JsPath::GetLength(napi_env env, napi_callback_info info)
339 {
340 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
341 return (me != nullptr) ? me->OnGetLength(env, info) : nullptr;
342 }
343
GetPositionAndTangent(napi_env env,napi_callback_info info)344 napi_value JsPath::GetPositionAndTangent(napi_env env, napi_callback_info info)
345 {
346 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
347 return (me != nullptr) ? me->OnGetPositionAndTangent(env, info) : nullptr;
348 }
349
Set(napi_env env,napi_callback_info info)350 napi_value JsPath::Set(napi_env env, napi_callback_info info)
351 {
352 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
353 return (me != nullptr) ? me->OnSet(env, info) : nullptr;
354 }
355
SetLastPoint(napi_env env,napi_callback_info info)356 napi_value JsPath::SetLastPoint(napi_env env, napi_callback_info info)
357 {
358 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
359 return (me != nullptr) ? me->OnSetLastPoint(env, info) : nullptr;
360 }
361
GetFillType(napi_env env,napi_callback_info info)362 napi_value JsPath::GetFillType(napi_env env, napi_callback_info info)
363 {
364 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
365 return (me != nullptr) ? me->OnGetFillType(env, info) : nullptr;
366 }
367
ReWind(napi_env env,napi_callback_info info)368 napi_value JsPath::ReWind(napi_env env, napi_callback_info info)
369 {
370 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
371 return (me != nullptr) ? me->OnReWind(env, info) : nullptr;
372 }
373
GetSegment(napi_env env,napi_callback_info info)374 napi_value JsPath::GetSegment(napi_env env, napi_callback_info info)
375 {
376 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
377 return (me != nullptr) ? me->OnGetSegment(env, info) : nullptr;
378 }
379
GetMatrix(napi_env env,napi_callback_info info)380 napi_value JsPath::GetMatrix(napi_env env, napi_callback_info info)
381 {
382 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
383 return (me != nullptr) ? me->OnGetMatrix(env, info) : nullptr;
384 }
385
BuildFromSvgString(napi_env env,napi_callback_info info)386 napi_value JsPath::BuildFromSvgString(napi_env env, napi_callback_info info)
387 {
388 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
389 return (me != nullptr) ? me->OnBuildFromSvgString(env, info) : nullptr;
390 }
391
IsClosed(napi_env env,napi_callback_info info)392 napi_value JsPath::IsClosed(napi_env env, napi_callback_info info)
393 {
394 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
395 return (me != nullptr) ? me->OnIsClosed(env, info) : nullptr;
396 }
397
IsEmpty(napi_env env,napi_callback_info info)398 napi_value JsPath::IsEmpty(napi_env env, napi_callback_info info)
399 {
400 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
401 return (me != nullptr) ? me->OnIsEmpty(env, info) : nullptr;
402 }
403
IsRect(napi_env env,napi_callback_info info)404 napi_value JsPath::IsRect(napi_env env, napi_callback_info info)
405 {
406 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
407 return (me != nullptr) ? me->OnIsRect(env, info) : nullptr;
408 }
409
Op(napi_env env,napi_callback_info info)410 napi_value JsPath::Op(napi_env env, napi_callback_info info)
411 {
412 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
413 return (me != nullptr) ? me->OnOp(env, info) : nullptr;
414 }
415
GetPathIterator(napi_env env,napi_callback_info info)416 napi_value JsPath::GetPathIterator(napi_env env, napi_callback_info info)
417 {
418 DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
419 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
420 return (me != nullptr) ? me->OnGetPathIterator(env, info) : nullptr;
421 }
422
Approximate(napi_env env,napi_callback_info info)423 napi_value JsPath::Approximate(napi_env env, napi_callback_info info)
424 {
425 DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
426 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
427 return (me != nullptr) ? me->OnApproximate(env, info) : nullptr;
428 }
429
Interpolate(napi_env env,napi_callback_info info)430 napi_value JsPath::Interpolate(napi_env env, napi_callback_info info)
431 {
432 DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
433 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
434 return (me != nullptr) ? me->OnInterpolate(env, info) : nullptr;
435 }
436
IsInterpolate(napi_env env,napi_callback_info info)437 napi_value JsPath::IsInterpolate(napi_env env, napi_callback_info info)
438 {
439 DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
440 JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
441 return (me != nullptr) ? me->OnIsInterpolate(env, info) : nullptr;
442 }
443
OnMoveTo(napi_env env,napi_callback_info info)444 napi_value JsPath::OnMoveTo(napi_env env, napi_callback_info info)
445 {
446 if (m_path == nullptr) {
447 ROSEN_LOGE("JsPath::OnMoveTo path is nullptr");
448 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
449 }
450
451 napi_value argv[ARGC_TWO] = {nullptr};
452 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
453
454 double x = 0.0;
455 GET_DOUBLE_PARAM(ARGC_ZERO, x);
456 double y = 0.0;
457 GET_DOUBLE_PARAM(ARGC_ONE, y);
458
459 JS_CALL_DRAWING_FUNC(m_path->MoveTo(x, y));
460 return nullptr;
461 }
462
OnLineTo(napi_env env,napi_callback_info info)463 napi_value JsPath::OnLineTo(napi_env env, napi_callback_info info)
464 {
465 if (m_path == nullptr) {
466 ROSEN_LOGE("JsPath::OnLineTo path is nullptr");
467 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
468 }
469
470 napi_value argv[ARGC_TWO] = {nullptr};
471 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
472
473 double x = 0.0;
474 GET_DOUBLE_PARAM(ARGC_ZERO, x);
475 double y = 0.0;
476 GET_DOUBLE_PARAM(ARGC_ONE, y);
477
478 JS_CALL_DRAWING_FUNC(m_path->LineTo(x, y));
479 return nullptr;
480 }
481
OnArcTo(napi_env env,napi_callback_info info)482 napi_value JsPath::OnArcTo(napi_env env, napi_callback_info info)
483 {
484 if (m_path == nullptr) {
485 ROSEN_LOGE("JsPath::OnArcTo path is nullptr");
486 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
487 }
488
489 napi_value argv[ARGC_SIX] = {nullptr};
490 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_SIX);
491
492 double x1 = 0.0;
493 GET_DOUBLE_PARAM(ARGC_ZERO, x1);
494 double y1 = 0.0;
495 GET_DOUBLE_PARAM(ARGC_ONE, y1);
496 double x2 = 0.0;
497 GET_DOUBLE_PARAM(ARGC_TWO, x2);
498 double y2 = 0.0;
499 GET_DOUBLE_PARAM(ARGC_THREE, y2);
500 double startDeg = 0.0;
501 GET_DOUBLE_PARAM(ARGC_FOUR, startDeg);
502 double sweepDeg = 0.0;
503 GET_DOUBLE_PARAM(ARGC_FIVE, sweepDeg);
504
505 JS_CALL_DRAWING_FUNC(m_path->ArcTo(x1, y1, x2, y2, startDeg, sweepDeg));
506 return nullptr;
507 }
508
OnQuadTo(napi_env env,napi_callback_info info)509 napi_value JsPath::OnQuadTo(napi_env env, napi_callback_info info)
510 {
511 if (m_path == nullptr) {
512 ROSEN_LOGE("JsPath::OnQuadTo path is nullptr");
513 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
514 }
515
516 napi_value argv[ARGC_FOUR] = {nullptr};
517 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_FOUR);
518
519 double ctrlPtX = 0.0;
520 GET_DOUBLE_PARAM(ARGC_ZERO, ctrlPtX);
521 double ctrlPtY = 0.0;
522 GET_DOUBLE_PARAM(ARGC_ONE, ctrlPtY);
523 double endPtX = 0.0;
524 GET_DOUBLE_PARAM(ARGC_TWO, endPtX);
525 double endPtY = 0.0;
526 GET_DOUBLE_PARAM(ARGC_THREE, endPtY);
527
528 JS_CALL_DRAWING_FUNC(m_path->QuadTo(ctrlPtX, ctrlPtY, endPtX, endPtY));
529 return nullptr;
530 }
531
OnConicTo(napi_env env,napi_callback_info info)532 napi_value JsPath::OnConicTo(napi_env env, napi_callback_info info)
533 {
534 if (m_path == nullptr) {
535 ROSEN_LOGE("JsPath::OnConicTo path is nullptr");
536 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
537 }
538
539 napi_value argv[ARGC_FIVE] = { nullptr };
540 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_FIVE);
541
542 double ctrlPtX = 0.0;
543 GET_DOUBLE_PARAM(ARGC_ZERO, ctrlPtX);
544 double ctrlPtY = 0.0;
545 GET_DOUBLE_PARAM(ARGC_ONE, ctrlPtY);
546 double endPtX = 0.0;
547 GET_DOUBLE_PARAM(ARGC_TWO, endPtX);
548 double endPtY = 0.0;
549 GET_DOUBLE_PARAM(ARGC_THREE, endPtY);
550 double weight = 0.0;
551 GET_DOUBLE_PARAM(ARGC_FOUR, weight);
552
553 m_path->ConicTo(ctrlPtX, ctrlPtY, endPtX, endPtY, weight);
554 return nullptr;
555 }
556
OnCubicTo(napi_env env,napi_callback_info info)557 napi_value JsPath::OnCubicTo(napi_env env, napi_callback_info info)
558 {
559 if (m_path == nullptr) {
560 ROSEN_LOGE("JsPath::OnCubicTo path is nullptr");
561 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
562 }
563
564 napi_value argv[ARGC_SIX] = {nullptr};
565 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_SIX);
566
567 double px1 = 0.0;
568 GET_DOUBLE_PARAM(ARGC_ZERO, px1);
569 double py1 = 0.0;
570 GET_DOUBLE_PARAM(ARGC_ONE, py1);
571 double px2 = 0.0;
572 GET_DOUBLE_PARAM(ARGC_TWO, px2);
573 double py2 = 0.0;
574 GET_DOUBLE_PARAM(ARGC_THREE, py2);
575 double px3 = 0.0;
576 GET_DOUBLE_PARAM(ARGC_FOUR, px3);
577 double py3 = 0.0;
578 GET_DOUBLE_PARAM(ARGC_FIVE, py3);
579
580 JS_CALL_DRAWING_FUNC(m_path->CubicTo(Point(px1, py1), Point(px2, py2), Point(px3, py3)));
581 return nullptr;
582 }
583
OnRMoveTo(napi_env env,napi_callback_info info)584 napi_value JsPath::OnRMoveTo(napi_env env, napi_callback_info info)
585 {
586 if (m_path == nullptr) {
587 ROSEN_LOGE("JsPath::OnRMoveTo path is nullptr");
588 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
589 }
590
591 napi_value argv[ARGC_TWO] = { nullptr };
592 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
593
594 double dx = 0.0;
595 GET_DOUBLE_PARAM(ARGC_ZERO, dx);
596 double dy = 0.0;
597 GET_DOUBLE_PARAM(ARGC_ONE, dy);
598
599 m_path->RMoveTo(dx, dy);
600 return nullptr;
601 }
602
OnRLineTo(napi_env env,napi_callback_info info)603 napi_value JsPath::OnRLineTo(napi_env env, napi_callback_info info)
604 {
605 if (m_path == nullptr) {
606 ROSEN_LOGE("JsPath::OnRLineTo path is nullptr");
607 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
608 }
609
610 napi_value argv[ARGC_TWO] = { nullptr };
611 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
612
613 double dx = 0.0;
614 GET_DOUBLE_PARAM(ARGC_ZERO, dx);
615 double dy = 0.0;
616 GET_DOUBLE_PARAM(ARGC_ONE, dy);
617
618 m_path->RLineTo(dx, dy);
619 return nullptr;
620 }
621
OnRQuadTo(napi_env env,napi_callback_info info)622 napi_value JsPath::OnRQuadTo(napi_env env, napi_callback_info info)
623 {
624 if (m_path == nullptr) {
625 ROSEN_LOGE("JsPath::OnRQuadTo path is nullptr");
626 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
627 }
628
629 napi_value argv[ARGC_FOUR] = { nullptr };
630 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_FOUR);
631
632 double dx1 = 0.0;
633 GET_DOUBLE_PARAM(ARGC_ZERO, dx1);
634 double dy1 = 0.0;
635 GET_DOUBLE_PARAM(ARGC_ONE, dy1);
636 double dx2 = 0.0;
637 GET_DOUBLE_PARAM(ARGC_TWO, dx2);
638 double dy2 = 0.0;
639 GET_DOUBLE_PARAM(ARGC_THREE, dy2);
640
641 m_path->RQuadTo(dx1, dy1, dx2, dy2);
642 return nullptr;
643 }
644
OnRConicTo(napi_env env,napi_callback_info info)645 napi_value JsPath::OnRConicTo(napi_env env, napi_callback_info info)
646 {
647 if (m_path == nullptr) {
648 ROSEN_LOGE("JsPath::OnRConicTo path is nullptr");
649 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
650 }
651
652 napi_value argv[ARGC_FIVE] = { nullptr };
653 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_FIVE);
654
655 double ctrlPtX = 0.0;
656 GET_DOUBLE_PARAM(ARGC_ZERO, ctrlPtX);
657 double ctrlPtY = 0.0;
658 GET_DOUBLE_PARAM(ARGC_ONE, ctrlPtY);
659 double endPtX = 0.0;
660 GET_DOUBLE_PARAM(ARGC_TWO, endPtX);
661 double endPtY = 0.0;
662 GET_DOUBLE_PARAM(ARGC_THREE, endPtY);
663 double weight = 0.0;
664 GET_DOUBLE_PARAM(ARGC_FOUR, weight);
665
666 m_path->RConicTo(ctrlPtX, ctrlPtY, endPtX, endPtY, weight);
667 return nullptr;
668 }
669
OnRCubicTo(napi_env env,napi_callback_info info)670 napi_value JsPath::OnRCubicTo(napi_env env, napi_callback_info info)
671 {
672 if (m_path == nullptr) {
673 ROSEN_LOGE("JsPath::OnRCubicTo path is nullptr");
674 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
675 }
676
677 napi_value argv[ARGC_SIX] = { nullptr };
678 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_SIX);
679
680 double px1 = 0.0;
681 GET_DOUBLE_PARAM(ARGC_ZERO, px1);
682 double py1 = 0.0;
683 GET_DOUBLE_PARAM(ARGC_ONE, py1);
684 double px2 = 0.0;
685 GET_DOUBLE_PARAM(ARGC_TWO, px2);
686 double py2 = 0.0;
687 GET_DOUBLE_PARAM(ARGC_THREE, py2);
688 double px3 = 0.0;
689 GET_DOUBLE_PARAM(ARGC_FOUR, px3);
690 double py3 = 0.0;
691 GET_DOUBLE_PARAM(ARGC_FIVE, py3);
692
693 m_path->RCubicTo(px1, py1, px2, py2, px3, py3);
694 return nullptr;
695 }
696
OnAddPolygon(napi_env env,napi_callback_info info)697 napi_value JsPath::OnAddPolygon(napi_env env, napi_callback_info info)
698 {
699 napi_value argv[ARGC_TWO] = { nullptr };
700 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
701
702 napi_value array = argv[ARGC_ZERO];
703 uint32_t size = 0;
704 napi_get_array_length(env, array, &size);
705 if (size == 0) {
706 return nullptr;
707 }
708 std::vector<Point> points;
709 points.reserve(size);
710 for (uint32_t i = 0; i < size; i++) {
711 napi_value tempRunBuffer = nullptr;
712 napi_get_element(env, array, i, &tempRunBuffer);
713
714 napi_value tempValue = nullptr;
715 Point point = Point();
716 double positionX = 0.0;
717 double positionY = 0.0;
718 napi_get_named_property(env, tempRunBuffer, "x", &tempValue);
719 bool isPositionXOk = ConvertFromJsValue(env, tempValue, positionX);
720 napi_get_named_property(env, tempRunBuffer, "y", &tempValue);
721 bool isPositionYOk = ConvertFromJsValue(env, tempValue, positionY);
722 if (!(isPositionXOk && isPositionYOk)) {
723 ROSEN_LOGE("JsPath::OnAddPolygon Argv is invalid");
724 return napi_value();
725 }
726
727 point.SetX(positionX);
728 point.SetY(positionY);
729 points.emplace_back(point);
730 }
731 if (points.size() != size) {
732 ROSEN_LOGE("JsPath::OnAddPolygon Argv is invalid");
733 return nullptr;
734 }
735
736 bool close = false;
737 GET_BOOLEAN_PARAM(ARGC_ONE, close);
738
739 m_path->AddPoly(points, size, close);
740 return nullptr;
741 }
742
OnOp(napi_env env,napi_callback_info info)743 napi_value JsPath::OnOp(napi_env env, napi_callback_info info)
744 {
745 if (m_path == nullptr) {
746 ROSEN_LOGE("JsPath::OnOp path is nullptr");
747 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
748 }
749
750 napi_value argv[ARGC_TWO] = {nullptr};
751 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
752
753 JsPath* jsPath = nullptr;
754 GET_UNWRAP_PARAM(ARGC_ZERO, jsPath);
755 if (jsPath->GetPath() == nullptr) {
756 ROSEN_LOGE("JsPath::OnOp path is nullptr");
757 return nullptr;
758 }
759
760 int32_t jsPathOp = 0;
761 GET_ENUM_PARAM(ARGC_ONE, jsPathOp, 0, static_cast<int32_t>(PathOp::REVERSE_DIFFERENCE));
762 return CreateJsValue(env, m_path->Op(*m_path, *jsPath->GetPath(), static_cast<PathOp>(jsPathOp)));
763 }
764
OnClose(napi_env env,napi_callback_info info)765 napi_value JsPath::OnClose(napi_env env, napi_callback_info info)
766 {
767 if (m_path == nullptr) {
768 ROSEN_LOGE("JsPath::OnClose path is nullptr");
769 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
770 }
771
772 JS_CALL_DRAWING_FUNC(m_path->Close());
773 return nullptr;
774 }
775
OnOffset(napi_env env,napi_callback_info info)776 napi_value JsPath::OnOffset(napi_env env, napi_callback_info info)
777 {
778 if (m_path == nullptr) {
779 ROSEN_LOGE("JsPath::OnOffset path is nullptr");
780 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
781 }
782
783 napi_value argv[ARGC_TWO] = { nullptr };
784 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
785
786 double dx = 0.0;
787 GET_DOUBLE_PARAM(ARGC_ZERO, dx);
788 double dy = 0.0;
789 GET_DOUBLE_PARAM(ARGC_ONE, dy);
790 Path* path = new Path();
791 m_path->Offset(path, dx, dy);
792 return CreateJsPath(env, path);
793 }
794
OnReset(napi_env env,napi_callback_info info)795 napi_value JsPath::OnReset(napi_env env, napi_callback_info info)
796 {
797 if (m_path == nullptr) {
798 ROSEN_LOGE("JsPath::OnReset path is nullptr");
799 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
800 }
801
802 JS_CALL_DRAWING_FUNC(m_path->Reset());
803 return nullptr;
804 }
805
OnGetLength(napi_env env,napi_callback_info info)806 napi_value JsPath::OnGetLength(napi_env env, napi_callback_info info)
807 {
808 if (m_path == nullptr) {
809 ROSEN_LOGE("JsPath::OnGetLength path is nullptr");
810 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
811 }
812 napi_value argv[ARGC_ONE] = {nullptr};
813 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
814
815 bool forceClosed = false;
816 GET_BOOLEAN_PARAM(ARGC_ZERO, forceClosed);
817
818 double len = m_path->GetLength(forceClosed);
819 return CreateJsNumber(env, len);
820 }
821
OnGetPositionAndTangent(napi_env env,napi_callback_info info)822 napi_value JsPath::OnGetPositionAndTangent(napi_env env, napi_callback_info info)
823 {
824 if (m_path == nullptr) {
825 ROSEN_LOGE("JsPath::OnGetPositionAndTangent path is nullptr");
826 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
827 }
828
829 napi_value argv[ARGC_FOUR] = {nullptr};
830 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_FOUR);
831
832 bool forceClosed = false;
833 GET_BOOLEAN_PARAM(ARGC_ZERO, forceClosed);
834
835 double distance = 0.0;
836 GET_DOUBLE_PARAM(ARGC_ONE, distance);
837
838 Drawing::Point position;
839 double startPoint[ARGC_TWO] = {0};
840 if (!ConvertFromJsPoint(env, argv[ARGC_TWO], startPoint, ARGC_TWO)) {
841 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
842 "Incorrect parameter2 type. The type of x, y be number.");
843 }
844 position = Drawing::Point(startPoint[ARGC_ZERO], startPoint[ARGC_ONE]);
845
846 Drawing::Point tangent;
847 double endPoint[ARGC_TWO] = {0};
848 if (!ConvertFromJsPoint(env, argv[ARGC_THREE], endPoint, ARGC_TWO)) {
849 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
850 "Incorrect parameter3 type. The type of x, y be number.");
851 }
852 tangent = Drawing::Point(endPoint[ARGC_ZERO], endPoint[ARGC_ONE]);
853
854 bool result = m_path->GetPositionAndTangent(distance, position, tangent, forceClosed);
855 if (napi_set_named_property(env, argv[ARGC_TWO], "x", CreateJsNumber(env, position.GetX())) != napi_ok ||
856 napi_set_named_property(env, argv[ARGC_TWO], "y", CreateJsNumber(env, position.GetY())) != napi_ok ||
857 napi_set_named_property(env, argv[ARGC_THREE], "x", CreateJsNumber(env, tangent.GetX())) != napi_ok ||
858 napi_set_named_property(env, argv[ARGC_THREE], "y", CreateJsNumber(env, tangent.GetY())) != napi_ok) {
859 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
860 "JsPath::OnGetPositionAndTangent Cannot fill 'position' and 'tangent' Point type.");
861 }
862 return CreateJsValue(env, result);
863 }
864
OnSet(napi_env env,napi_callback_info info)865 napi_value JsPath::OnSet(napi_env env, napi_callback_info info)
866 {
867 if (m_path == nullptr) {
868 ROSEN_LOGE("JsPath::OnSet path is nullptr");
869 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
870 }
871 napi_value argv[ARGC_ONE] = {nullptr};
872 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
873
874 JsPath* path = nullptr;
875 GET_UNWRAP_PARAM(ARGC_ZERO, path);
876 if (path->GetPath() == nullptr) {
877 return nullptr;
878 }
879 JS_CALL_DRAWING_FUNC(m_path->SetPath(*path->GetPath()));
880 return nullptr;
881 }
882
OnSetLastPoint(napi_env env,napi_callback_info info)883 napi_value JsPath::OnSetLastPoint(napi_env env, napi_callback_info info)
884 {
885 if (m_path == nullptr) {
886 ROSEN_LOGE("JsPath::OnSetLastPoint path is nullptr");
887 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
888 }
889 napi_value argv[ARGC_TWO] = {nullptr};
890 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
891 double x = 0.0;
892 GET_DOUBLE_PARAM(ARGC_ZERO, x);
893 double y = 0.0;
894 GET_DOUBLE_PARAM(ARGC_ONE, y);
895 JS_CALL_DRAWING_FUNC(m_path->SetLastPoint(x, y));
896 return nullptr;
897 }
898
OnGetFillType(napi_env env,napi_callback_info info)899 napi_value JsPath::OnGetFillType(napi_env env, napi_callback_info info)
900 {
901 if (m_path == nullptr) {
902 ROSEN_LOGE("JsPath::OnGetFillType path is nullptr");
903 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
904 }
905
906 return CreateJsValue(env, m_path->GetFillStyle());
907 }
908
OnReWind(napi_env env,napi_callback_info info)909 napi_value JsPath::OnReWind(napi_env env, napi_callback_info info)
910 {
911 if (m_path == nullptr) {
912 ROSEN_LOGE("JsPath::OnRewind path is nullptr");
913 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
914 }
915 JS_CALL_DRAWING_FUNC(m_path->ReWind());
916 return nullptr;
917 }
918
OnGetSegment(napi_env env,napi_callback_info info)919 napi_value JsPath::OnGetSegment(napi_env env, napi_callback_info info)
920 {
921 if (m_path == nullptr) {
922 ROSEN_LOGE("JsPath::OnGetSegment path is nullptr");
923 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
924 }
925 napi_value argv[ARGC_FIVE] = {nullptr};
926 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_FIVE);
927
928 bool forceClosed = false;
929 GET_BOOLEAN_PARAM(ARGC_ZERO, forceClosed);
930 double start = 0.0;
931 GET_DOUBLE_PARAM(ARGC_ONE, start);
932 double stop = 0.0;
933 GET_DOUBLE_PARAM(ARGC_TWO, stop);
934 bool startWithMoveTo = false;
935 GET_BOOLEAN_PARAM(ARGC_THREE, startWithMoveTo);
936 JsPath* jsPath = nullptr;
937 GET_UNWRAP_PARAM(ARGC_FOUR, jsPath);
938
939 Path* dst = jsPath->GetPath();
940 if (dst == nullptr) {
941 ROSEN_LOGE("JsPath::OnGetSegment dst is nullptr");
942 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect OnGetSegment parameter3 type.");
943 }
944
945 double length = m_path->GetLength(forceClosed);
946 if (start < 0) {
947 start = 0;
948 }
949 if (stop > length) {
950 stop = length;
951 }
952 if (start >= stop) {
953 return CreateJsValue(env, false);
954 }
955 return CreateJsValue(env, m_path->GetSegment(start, stop, dst, startWithMoveTo, forceClosed));
956 }
957
OnIsEmpty(napi_env env,napi_callback_info info)958 napi_value JsPath::OnIsEmpty(napi_env env, napi_callback_info info)
959 {
960 if (m_path == nullptr) {
961 ROSEN_LOGE("JsPath::OnIsEmpty path is nullptr");
962 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
963 }
964
965 bool result = m_path->IsEmpty();
966 return CreateJsValue(env, result);
967 }
968
OnIsRect(napi_env env,napi_callback_info info)969 napi_value JsPath::OnIsRect(napi_env env, napi_callback_info info)
970 {
971 if (m_path == nullptr) {
972 ROSEN_LOGE("JsPath::OnIsRect path is nullptr");
973 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
974 }
975
976 napi_value argv[ARGC_ONE] = {nullptr};
977 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
978 napi_valuetype valueType = napi_undefined;
979 if (napi_typeof(env, argv[ARGC_ZERO], &valueType) != napi_ok ||
980 (valueType != napi_null && valueType != napi_object)) {
981 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect OnSaveLayer parameter0 type.");
982 }
983 if (valueType == napi_null) {
984 return CreateJsValue(env, m_path->IsRect(nullptr));
985 }
986 double ltrb[ARGC_FOUR] = {0};
987 if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
988 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
989 "Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
990 }
991 Drawing::Rect rect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
992 bool result = m_path->IsRect(&rect);
993 DrawingRectConvertToJsRect(env, argv[ARGC_ZERO], rect);
994 return CreateJsValue(env, result);
995 }
996
OnGetMatrix(napi_env env,napi_callback_info info)997 napi_value JsPath::OnGetMatrix(napi_env env, napi_callback_info info)
998 {
999 if (m_path == nullptr) {
1000 ROSEN_LOGE("JsPath::OnGetMatrix path is nullptr");
1001 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1002 }
1003
1004 napi_value argv[ARGC_FOUR] = {nullptr};
1005 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_FOUR);
1006
1007 bool forceClosed = false;
1008 GET_BOOLEAN_PARAM(ARGC_ZERO, forceClosed);
1009
1010 double distance = 0.0;
1011 GET_DOUBLE_PARAM(ARGC_ONE, distance);
1012
1013 JsMatrix* jsMatrix = nullptr;
1014 GET_UNWRAP_PARAM(ARGC_TWO, jsMatrix);
1015
1016 if (jsMatrix->GetMatrix() == nullptr) {
1017 ROSEN_LOGE("JsPath::OnGetMatrix jsMatrix is nullptr");
1018 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1019 }
1020
1021 int32_t flag = 0;
1022 GET_ENUM_PARAM(ARGC_THREE, flag, 0,
1023 static_cast<int32_t>(PathMeasureMatrixFlags::GET_POS_AND_TAN_MATRIX));
1024 bool result = m_path->GetMatrix(
1025 forceClosed,
1026 distance,
1027 jsMatrix->GetMatrix().get(),
1028 static_cast<PathMeasureMatrixFlags>(flag));
1029 return CreateJsValue(env, result);
1030 }
1031
OnBuildFromSvgString(napi_env env,napi_callback_info info)1032 napi_value JsPath::OnBuildFromSvgString(napi_env env, napi_callback_info info)
1033 {
1034 if (m_path == nullptr) {
1035 ROSEN_LOGE("JsPath::OnBuildFromSVGString path is nullptr");
1036 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1037 }
1038
1039 napi_value argv[ARGC_ONE] = { nullptr };
1040 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1041
1042 std::string str = {""};
1043 if (!(ConvertFromJsValue(env, argv[ARGC_ZERO], str))) {
1044 ROSEN_LOGE("JsPath::OnBuildFromSVGString Argv is invalid");
1045 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1046 }
1047
1048 bool result = m_path->BuildFromSVGString(str);
1049 return CreateJsValue(env, result);
1050 }
1051
OnAddOval(napi_env env,napi_callback_info info)1052 napi_value JsPath::OnAddOval(napi_env env, napi_callback_info info)
1053 {
1054 if (m_path == nullptr) {
1055 ROSEN_LOGE("JsPath::OnAddOval path is nullptr");
1056 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1057 }
1058
1059 size_t argc = ARGC_THREE;
1060 napi_value argv[ARGC_THREE] = {nullptr};
1061 CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_TWO, ARGC_THREE);
1062
1063 Drawing::Rect drawingRect;
1064 double ltrb[ARGC_FOUR] = {0};
1065 if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
1066 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
1067 "Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
1068 }
1069 drawingRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
1070
1071 int32_t start = 0;
1072 GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_ONE, start);
1073 if (argc == ARGC_TWO) {
1074 JS_CALL_DRAWING_FUNC(m_path->AddOval(drawingRect, start,
1075 static_cast<PathDirection>(PathDirection::CW_DIRECTION)));
1076 return nullptr;
1077 }
1078 int32_t jsDirection = 0;
1079 GET_ENUM_PARAM(ARGC_TWO, jsDirection, 0, static_cast<int32_t>(PathDirection::CCW_DIRECTION));
1080
1081 JS_CALL_DRAWING_FUNC(m_path->AddOval(drawingRect, start, static_cast<PathDirection>(jsDirection)));
1082 return nullptr;
1083 }
1084
OnAddCircle(napi_env env,napi_callback_info info)1085 napi_value JsPath::OnAddCircle(napi_env env, napi_callback_info info)
1086 {
1087 if (m_path == nullptr) {
1088 ROSEN_LOGE("JsPath::OnAddCircle path is nullptr");
1089 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1090 }
1091
1092 size_t argc = ARGC_FOUR;
1093 napi_value argv[ARGC_FOUR] = {nullptr};
1094 CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_THREE, ARGC_FOUR);
1095
1096 double px1 = 0.0;
1097 GET_DOUBLE_PARAM(ARGC_ZERO, px1);
1098 double py1 = 0.0;
1099 GET_DOUBLE_PARAM(ARGC_ONE, py1);
1100 double radius = 0.0;
1101 GET_DOUBLE_PARAM(ARGC_TWO, radius);
1102 if (argc == ARGC_THREE) {
1103 JS_CALL_DRAWING_FUNC(m_path->AddCircle(px1, py1, radius));
1104 return nullptr;
1105 }
1106 int32_t jsDirection = 0;
1107 GET_ENUM_PARAM(ARGC_THREE, jsDirection, 0, static_cast<int32_t>(PathDirection::CCW_DIRECTION));
1108
1109 JS_CALL_DRAWING_FUNC(m_path->AddCircle(px1, py1, radius, static_cast<PathDirection>(jsDirection)));
1110 return nullptr;
1111 }
1112
OnAddArc(napi_env env,napi_callback_info info)1113 napi_value JsPath::OnAddArc(napi_env env, napi_callback_info info)
1114 {
1115 if (m_path == nullptr) {
1116 ROSEN_LOGE("JsPath::OnAddArc path is nullptr");
1117 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1118 }
1119
1120 napi_value argv[ARGC_THREE] = {nullptr};
1121 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
1122
1123 Drawing::Rect drawingRect;
1124 double ltrb[ARGC_FOUR] = {0};
1125 if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
1126 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
1127 "Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
1128 }
1129 drawingRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
1130
1131 double startDeg = 0.0;
1132 GET_DOUBLE_PARAM(ARGC_ONE, startDeg);
1133 double sweepDeg = 0.0;
1134 GET_DOUBLE_PARAM(ARGC_TWO, sweepDeg);
1135
1136 JS_CALL_DRAWING_FUNC(m_path->AddArc(drawingRect, startDeg, sweepDeg));
1137 return nullptr;
1138 }
1139
OnAddRect(napi_env env,napi_callback_info info)1140 napi_value JsPath::OnAddRect(napi_env env, napi_callback_info info)
1141 {
1142 if (m_path == nullptr) {
1143 ROSEN_LOGE("JsPath::OnAddRect path is nullptr");
1144 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1145 }
1146
1147 size_t argc = ARGC_TWO;
1148 napi_value argv[ARGC_TWO] = {nullptr};
1149 CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ONE, ARGC_TWO);
1150
1151 Drawing::Rect drawingRect;
1152 double ltrb[ARGC_FOUR] = {0};
1153 if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
1154 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
1155 "Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
1156 }
1157 drawingRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
1158 if (argc == ARGC_ONE) {
1159 JS_CALL_DRAWING_FUNC(m_path->AddRect(drawingRect));
1160 return nullptr;
1161 }
1162 int32_t jsDirection = 0;
1163 GET_ENUM_PARAM(ARGC_ONE, jsDirection, 0, static_cast<int32_t>(PathDirection::CCW_DIRECTION));
1164
1165 JS_CALL_DRAWING_FUNC(m_path->AddRect(drawingRect, static_cast<PathDirection>(jsDirection)));
1166 return nullptr;
1167 }
1168
OnAddRoundRect(napi_env env,napi_callback_info info)1169 napi_value JsPath::OnAddRoundRect(napi_env env, napi_callback_info info)
1170 {
1171 if (m_path == nullptr) {
1172 ROSEN_LOGE("JsPath::OnAddRoundRect path is nullptr");
1173 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1174 }
1175
1176 size_t argc = ARGC_TWO;
1177 napi_value argv[ARGC_TWO] = {nullptr};
1178 CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ONE, ARGC_TWO);
1179
1180 JsRoundRect* jsRoundRect = nullptr;
1181 GET_UNWRAP_PARAM(ARGC_ZERO, jsRoundRect);
1182 if (argc == ARGC_ONE) {
1183 JS_CALL_DRAWING_FUNC(m_path->AddRoundRect(jsRoundRect->GetRoundRect()));
1184 return nullptr;
1185 }
1186 int32_t jsDirection = 0;
1187 GET_ENUM_PARAM(ARGC_ONE, jsDirection, 0, static_cast<int32_t>(PathDirection::CCW_DIRECTION));
1188
1189 JS_CALL_DRAWING_FUNC(m_path->AddRoundRect(jsRoundRect->GetRoundRect(), static_cast<PathDirection>(jsDirection)));
1190 return nullptr;
1191 }
1192
OnAddPath(napi_env env,napi_callback_info info)1193 napi_value JsPath::OnAddPath(napi_env env, napi_callback_info info)
1194 {
1195 if (m_path == nullptr) {
1196 ROSEN_LOGE("JsPath::OnAddPath path is nullptr");
1197 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1198 }
1199
1200 size_t argc = ARGC_TWO;
1201 napi_value argv[ARGC_TWO] = {nullptr};
1202 CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ONE, ARGC_TWO);
1203
1204 JsPath* jsPath = nullptr;
1205 GET_UNWRAP_PARAM(ARGC_ZERO, jsPath);
1206 if (jsPath->GetPath() == nullptr) {
1207 ROSEN_LOGE("JsPath::OnAddPath path is nullptr");
1208 return nullptr;
1209 }
1210 if (argc == ARGC_ONE) {
1211 JS_CALL_DRAWING_FUNC(m_path->AddPath(*jsPath->GetPath(), Drawing::Matrix()));
1212 return nullptr;
1213 }
1214 Drawing::Matrix* drawingMatrixPtr = nullptr;
1215 napi_valuetype valueType = napi_undefined;
1216 if (napi_typeof(env, argv[ARGC_ONE], &valueType) != napi_ok ||
1217 (valueType != napi_null && valueType != napi_object)) {
1218 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect OnAddPath parameter1 type.");
1219 }
1220 if (valueType == napi_object) {
1221 JsMatrix* jsMatrix = nullptr;
1222 GET_UNWRAP_PARAM(ARGC_ONE, jsMatrix);
1223 if (jsMatrix->GetMatrix() != nullptr) {
1224 drawingMatrixPtr = jsMatrix->GetMatrix().get();
1225 }
1226 }
1227 JS_CALL_DRAWING_FUNC(m_path->AddPath(*jsPath->GetPath(),
1228 drawingMatrixPtr ? *drawingMatrixPtr : Drawing::Matrix()));
1229 return nullptr;
1230 }
1231
OnTransform(napi_env env,napi_callback_info info)1232 napi_value JsPath::OnTransform(napi_env env, napi_callback_info info)
1233 {
1234 if (m_path == nullptr) {
1235 ROSEN_LOGE("JsPath::OnTransform path is nullptr");
1236 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1237 }
1238
1239 napi_value argv[ARGC_ONE] = {nullptr};
1240 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1241
1242 JsMatrix* jsMatrix = nullptr;
1243 GET_UNWRAP_PARAM(ARGC_ZERO, jsMatrix);
1244 if (jsMatrix->GetMatrix() == nullptr) {
1245 ROSEN_LOGE("JsPath::OnAddPath Matrix is nullptr");
1246 return nullptr;
1247 }
1248
1249 JS_CALL_DRAWING_FUNC(m_path->Transform(*jsMatrix->GetMatrix()));
1250 return nullptr;
1251 }
1252
OnContains(napi_env env,napi_callback_info info)1253 napi_value JsPath::OnContains(napi_env env, napi_callback_info info)
1254 {
1255 if (m_path == nullptr) {
1256 ROSEN_LOGE("JsPath::OnContains path is nullptr");
1257 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1258 }
1259
1260 napi_value argv[ARGC_TWO] = {nullptr};
1261 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
1262
1263 double x = 0.0;
1264 GET_DOUBLE_PARAM(ARGC_ZERO, x);
1265 double y = 0.0;
1266 GET_DOUBLE_PARAM(ARGC_ONE, y);
1267
1268 return CreateJsValue(env, m_path->Contains(x, y));
1269 }
1270
OnSetFillType(napi_env env,napi_callback_info info)1271 napi_value JsPath::OnSetFillType(napi_env env, napi_callback_info info)
1272 {
1273 if (m_path == nullptr) {
1274 ROSEN_LOGE("JsPath::OnSetFillType path is nullptr");
1275 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1276 }
1277
1278 napi_value argv[ARGC_ONE] = {nullptr};
1279 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1280
1281 int32_t jsFillType = 0;
1282 GET_ENUM_PARAM(ARGC_ZERO, jsFillType, 0, static_cast<int32_t>(PathFillType::INVERSE_EVENTODD));
1283
1284 JS_CALL_DRAWING_FUNC(m_path->SetFillStyle(static_cast<PathFillType>(jsFillType)));
1285 return nullptr;
1286 }
1287
OnGetBounds(napi_env env,napi_callback_info info)1288 napi_value JsPath::OnGetBounds(napi_env env, napi_callback_info info)
1289 {
1290 if (m_path == nullptr) {
1291 ROSEN_LOGE("JsPath::OnGetBounds path is nullptr");
1292 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1293 }
1294 return GetRectAndConvertToJsValue(env, m_path->GetBounds());
1295 }
1296
OnIsClosed(napi_env env,napi_callback_info info)1297 napi_value JsPath::OnIsClosed(napi_env env, napi_callback_info info)
1298 {
1299 if (m_path == nullptr) {
1300 ROSEN_LOGE("JsPath::OnIsClosed path is nullptr");
1301 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1302 }
1303
1304 bool result = m_path->IsClosed(false);
1305 return CreateJsValue(env, result);
1306 }
1307
OnGetPathIterator(napi_env env,napi_callback_info info)1308 napi_value JsPath::OnGetPathIterator(napi_env env, napi_callback_info info)
1309 {
1310 if (m_path == nullptr) {
1311 ROSEN_LOGE("JsPath::OnGetPathIterator path is nullptr");
1312 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1313 }
1314
1315 DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
1316 PathIterator *iter = new PathIterator(*m_path);
1317 return JsPathIterator::CreateJsPathIterator(env, iter);
1318 }
1319
OnApproximate(napi_env env,napi_callback_info info)1320 napi_value JsPath::OnApproximate(napi_env env, napi_callback_info info)
1321 {
1322 if (m_path == nullptr) {
1323 ROSEN_LOGE("JsPath::OnApproximate path is nullptr");
1324 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1325 }
1326 napi_value argv[ARGC_ONE] = { nullptr };
1327 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1328 double acceptableError = 0.0;
1329 GET_DOUBLE_PARAM(ARGC_ZERO, acceptableError);
1330 if (acceptableError < 0.0) {
1331 ROSEN_LOGE("JsPath::OnApproximate acceptableError is invalid");
1332 return NapiThrowError(env, DrawingErrorCode::ERROR_PARAM_VERIFICATION_FAILED, "acceptableError is invalid.");
1333 }
1334 std::vector<scalar> points;
1335 DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
1336 m_path->Approximate(static_cast<scalar>(acceptableError), points);
1337
1338 napi_value resultArray;
1339 napi_status status = napi_create_array(env, &resultArray);
1340 if (status != napi_ok) {
1341 ROSEN_LOGE("JsPath::OnApproximate failed to create array");
1342 return nullptr;
1343 }
1344 for (size_t i = 0; i < points.size(); i++) {
1345 napi_value element = CreateJsValue(env, points[i]);
1346 napi_set_element(env, resultArray, i, element);
1347 }
1348
1349 return resultArray;
1350 }
1351
OnInterpolate(napi_env env,napi_callback_info info)1352 napi_value JsPath::OnInterpolate(napi_env env, napi_callback_info info)
1353 {
1354 if (m_path == nullptr) {
1355 ROSEN_LOGE("JsPath::OnInterpolate path is nullptr");
1356 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1357 }
1358 napi_value argv[ARGC_THREE] = { nullptr };
1359 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
1360
1361 JsPath* other = nullptr;
1362 GET_UNWRAP_PARAM(ARGC_ZERO, other);
1363 if (other->GetPath() == nullptr) {
1364 ROSEN_LOGE("JsPath::OnInterpolate other is nullptr");
1365 return nullptr;
1366 }
1367 double weight = 0.0;
1368 GET_DOUBLE_PARAM(ARGC_ONE, weight);
1369 if (weight < 0.0 || weight > 1.0) {
1370 ROSEN_LOGE("JsPath::OnInterpolate weight is invalid");
1371 return NapiThrowError(env, DrawingErrorCode::ERROR_PARAM_VERIFICATION_FAILED, "weight is invalid.");
1372 }
1373 JsPath* interpolatedPath = nullptr;
1374 GET_UNWRAP_PARAM(ARGC_TWO, interpolatedPath);
1375 if (interpolatedPath->GetPath() == nullptr) {
1376 ROSEN_LOGE("JsPath::OnInterpolate interpolatedPath is nullptr");
1377 return nullptr;
1378 }
1379 DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
1380 bool result = m_path->Interpolate(*other->GetPath(), weight, *interpolatedPath->GetPath());
1381 return CreateJsValue(env, result);
1382 }
1383
OnIsInterpolate(napi_env env,napi_callback_info info)1384 napi_value JsPath::OnIsInterpolate(napi_env env, napi_callback_info info)
1385 {
1386 if (m_path == nullptr) {
1387 ROSEN_LOGE("JsPath::OnIsInterpolate path is nullptr");
1388 return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
1389 }
1390 napi_value argv[ARGC_ONE] = {nullptr};
1391 CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
1392 JsPath* other = nullptr;
1393 GET_UNWRAP_PARAM(ARGC_ZERO, other);
1394 if (other->GetPath() == nullptr) {
1395 ROSEN_LOGE("JsPath::OnIsInterpolate other is nullptr");
1396 return nullptr;
1397 }
1398 DRAWING_PERFORMANCE_TEST_NAP_RETURN(nullptr);
1399 bool result = m_path->IsInterpolate(*other->GetPath());
1400 return CreateJsValue(env, result);
1401 }
GetPath()1402 Path* JsPath::GetPath()
1403 {
1404 return m_path;
1405 }
1406 } // namespace Drawing
1407 } // namespace OHOS::Rosen
1408