1 /*
2 * Copyright (c) 2024 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 #ifdef ROSEN_OHOS
17 #include <regex>
18 #include "ability.h"
19 #endif
20
21 #include "js_drawing_utils.h"
22 #include "js_tool.h"
23
24
25 namespace OHOS::Rosen {
26 namespace Drawing {
27 thread_local napi_ref JsTool::constructor_ = nullptr;
28 const std::string CLASS_NAME = "Tool";
29 #ifdef ROSEN_OHOS
30 const int32_t GLOBAL_ERROR = 10000;
31 // The expectLength of regex match of "rgb(255,0,0)". The elements:0 is the string, 1 is r, 2 is g, 3 is b.
32 constexpr uint32_t RGB_SUB_MATCH_SIZE = 4;
33 // The expectLength of regex match of "rgba(255,0,0,0.5)". The elements:0 is the string, 1 is r, 2 is g, 3 is b, 4 is a.
34 constexpr uint32_t RGBA_SUB_MATCH_SIZE = 7;
35 // The length of standard color, the length of str is must like "FF00FF00" which length is 8.
36 constexpr uint32_t COLOR_STRING_SIZE_STANDARD = 8;
37 constexpr uint32_t COLOR_OFFSET_GREEN = 8;
38 constexpr uint32_t COLOR_OFFSET_RED = 16;
39 // The string will be parsed in hexadecimal format during the conversion
40 constexpr uint32_t COLOR_STRING_FORMAT = 16;
41 constexpr uint32_t COLOR_OFFSET_ALPHA = 24;
42 constexpr uint32_t COLOR_DEFAULT_ALPHA = 0xFF000000;
43 const std::vector<size_t> EXPECT_MAGIC_COLOR_LENGTHS = {7, 9};
44 const std::vector<size_t> EXPECT_MAGIC_MINI_COLOR_LENGTHS = {4, 5};
45 const std::regex COLOR_WITH_RGB(R"(rgb\(([+]?[0-9]+)\,([+]?[0-9]+)\,([+]?[0-9]+)\))", std::regex::icase);
46 const std::regex COLOR_WITH_RGBA(R"(rgba\(([+]?[0-9]+)\,([+]?[0-9]+)\,([+]?[0-9]+)\,((0|1)(\.\d+)?)\))",
47 std::regex::icase);
48 const std::regex HEX_PATTERN("^[0-9a-fA-F]+$");
49 #endif
Init(napi_env env,napi_value exportObj)50 napi_value JsTool::Init(napi_env env, napi_value exportObj)
51 {
52 napi_property_descriptor properties[] = {
53 DECLARE_NAPI_STATIC_FUNCTION("makeColorFromResourceColor", JsTool::makeColorFromResourceColor),
54 };
55
56 napi_value constructor = nullptr;
57 napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
58 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
59 if (status != napi_ok) {
60 ROSEN_LOGE("JsTool::Init failed to define Tool class");
61 return nullptr;
62 }
63
64 status = napi_create_reference(env, constructor, 1, &constructor_);
65 if (status != napi_ok) {
66 ROSEN_LOGE("JsTool::Init Failed to create reference of constructor");
67 return nullptr;
68 }
69
70 status = napi_set_named_property(env, exportObj, CLASS_NAME.c_str(), constructor);
71 if (status != napi_ok) {
72 ROSEN_LOGE("JsTool::Init Failed to set constructor");
73 return nullptr;
74 }
75
76 return exportObj;
77 }
78
Constructor(napi_env env,napi_callback_info info)79 napi_value JsTool::Constructor(napi_env env, napi_callback_info info)
80 {
81 size_t argCount = 0;
82 napi_value jsThis = nullptr;
83 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
84 if (status != napi_ok) {
85 ROSEN_LOGE("JsTool::Constructor failed to napi_get_cb_info");
86 return nullptr;
87 }
88
89 JsTool* jsTool = new JsTool();
90 if (jsTool == nullptr) {
91 ROSEN_LOGE("JsTool::Constructor jsTool is nullptr");
92 return nullptr;
93 }
94
95 status = napi_wrap(env, jsThis, jsTool, JsTool::Destructor, nullptr, nullptr);
96 if (status != napi_ok) {
97 delete jsTool;
98 ROSEN_LOGE("JsTool::Constructor Failed to wrap native instance");
99 return nullptr;
100 }
101 return jsThis;
102 }
103
Destructor(napi_env env,void * nativeObject,void * finalize)104 void JsTool::Destructor(napi_env env, void *nativeObject, void *finalize)
105 {
106 (void)finalize;
107 if (nativeObject != nullptr) {
108 JsTool *napi = reinterpret_cast<JsTool *>(nativeObject);
109 delete napi;
110 }
111 }
112
JsTool()113 JsTool::JsTool() {}
114
~JsTool()115 JsTool::~JsTool() {}
116
makeColorFromResourceColor(napi_env env,napi_callback_info info)117 napi_value JsTool::makeColorFromResourceColor(napi_env env, napi_callback_info info)
118 {
119 #ifdef ROSEN_OHOS
120 size_t argc = ARGC_ONE;
121 napi_value argv[ARGC_ONE] = {nullptr};
122 CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_ONE, ARGC_ONE);
123
124 uint32_t colorNumber = 0;
125 if (!GetResourceColor(env, argv[ARGC_ZERO], colorNumber)) {
126 ROSEN_LOGE("JsTool::makeColorFromResourceColor failed to get colorNumber!");
127 return nullptr;
128 }
129
130 napi_value objColor = nullptr;
131 napi_create_object(env, &objColor);
132 if (objColor == nullptr) {
133 ROSEN_LOGE("JsTool::makeColorFromResourceColor failed to create color!");
134 return nullptr;
135 }
136
137 napi_set_named_property(env, objColor, "alpha", CreateJsNumber(env, (colorNumber >> COLOR_OFFSET_ALPHA) & 0xFF));
138 napi_set_named_property(env, objColor, "red", CreateJsNumber(env, (colorNumber >> COLOR_OFFSET_RED) & 0xFF));
139 napi_set_named_property(env, objColor, "green", CreateJsNumber(env, (colorNumber >> COLOR_OFFSET_GREEN) & 0xFF));
140 napi_set_named_property(env, objColor, "blue", CreateJsNumber(env, colorNumber & 0xFF));
141
142 return objColor;
143 #else
144 return nullptr;
145 #endif
146 }
147
148 #ifdef ROSEN_OHOS
GetParamLen(napi_env env,napi_value param)149 size_t JsTool::GetParamLen(napi_env env, napi_value param)
150 {
151 size_t buffSize = 0;
152 napi_status status = napi_get_value_string_utf8(env, param, nullptr, 0, &buffSize);
153 if (status != napi_ok || buffSize == 0) {
154 return 0;
155 }
156 return buffSize;
157 }
158
GetResourceManager()159 std::shared_ptr<Global::Resource::ResourceManager> JsTool::GetResourceManager()
160 {
161 std::shared_ptr<AbilityRuntime::ApplicationContext> context =
162 AbilityRuntime::ApplicationContext::GetApplicationContext();
163 if (context == nullptr) {
164 ROSEN_LOGE("JsTool::Failed to get application context");
165 return nullptr;
166 }
167 auto resourceManager = context->GetResourceManager();
168 if (resourceManager == nullptr) {
169 ROSEN_LOGE("JsTool::Failed to get resource manager");
170 return nullptr;
171 }
172 return resourceManager;
173 }
174
GetResourceInfo(napi_env env,napi_value value,ResourceInfo & info)175 bool JsTool::GetResourceInfo(napi_env env, napi_value value, ResourceInfo& info)
176 {
177 napi_valuetype valueType = napi_undefined;
178 napi_typeof(env, value, &valueType);
179 if (valueType != napi_object) {
180 ROSEN_LOGE("JsTool::GetResourceInfo the value is not object!");
181 return false;
182 }
183
184 napi_value idNApi = nullptr;
185 napi_value typeNApi = nullptr;
186 napi_value paramsNApi = nullptr;
187 napi_get_named_property(env, value, "id", &idNApi);
188 napi_get_named_property(env, value, "type", &typeNApi);
189 napi_get_named_property(env, value, "params", ¶msNApi);
190
191 napi_typeof(env, idNApi, &valueType);
192 if (valueType != napi_number) {
193 ROSEN_LOGE("JsTool::GetResourceInfo id is not number!");
194 return false;
195 }
196 napi_get_value_int32(env, idNApi, &info.resId);
197
198 napi_typeof(env, typeNApi, &valueType);
199 if (valueType != napi_number) {
200 ROSEN_LOGE("JsTool::GetResourceInfo type is not number!");
201 return false;
202 }
203 napi_get_value_int32(env, typeNApi, &info.type);
204
205 return GetResourceInfoParams(env, info, paramsNApi);
206 }
207
GetResourceInfoParams(napi_env env,ResourceInfo & info,napi_value paramsNApi)208 bool JsTool::GetResourceInfoParams(napi_env env, ResourceInfo& info, napi_value paramsNApi)
209 {
210 napi_valuetype valueType = napi_undefined;
211 bool isArray = false;
212 if (napi_is_array(env, paramsNApi, &isArray) != napi_ok) {
213 ROSEN_LOGE("JsTool::Failed to get array type");
214 return false;
215 }
216 if (!isArray) {
217 ROSEN_LOGE("JsTool::Invalid array type");
218 return false;
219 }
220
221 // Here we use 'for' to get all params
222 uint32_t arrayLength = 0;
223 napi_get_array_length(env, paramsNApi, &arrayLength);
224 for (uint32_t i = 0; i < arrayLength; i++) {
225 size_t ret = 0;
226 napi_value indexValue = nullptr;
227 napi_get_element(env, paramsNApi, i, &indexValue);
228 napi_typeof(env, indexValue, &valueType);
229 if (valueType == napi_string) {
230 size_t strlen = GetParamLen(env, indexValue) + 1;
231 std::unique_ptr<char[]> indexStr = std::make_unique<char[]>(strlen);
232 napi_get_value_string_utf8(env, indexValue, indexStr.get(), strlen, &ret);
233 info.params.emplace_back(indexStr.get());
234 } else if (valueType == napi_number) {
235 int32_t num = 0;
236 napi_get_value_int32(env, indexValue, &num);
237 info.params.emplace_back(std::to_string(num));
238 } else {
239 ROSEN_LOGE("JsTool::Invalid value type %{public}d", valueType);
240 return false;
241 }
242 }
243
244 return true;
245 }
246
GetResourceRawFileDataBuffer(std::unique_ptr<uint8_t[]> && buffer,size_t & len,ResourceInfo & info)247 bool JsTool::GetResourceRawFileDataBuffer(std::unique_ptr<uint8_t[]>&& buffer, size_t& len, ResourceInfo& info)
248 {
249 auto resourceManager = GetResourceManager();
250 if (resourceManager == nullptr) {
251 ROSEN_LOGE("JsTool::Failed to get resourceManager, resourceManager is nullptr");
252 return false;
253 }
254 if (info.type != static_cast<int32_t>(ResourceType::RAWFILE)) {
255 ROSEN_LOGE("JsTool::Invalid resource type %{public}d", info.type);
256 return false;
257 }
258
259 int32_t state = 0;
260
261 if (info.params.empty()) {
262 ROSEN_LOGE("JsTool::Failed to get RawFile resource, RawFile is null");
263 return false;
264 }
265
266 state = resourceManager->GetRawFileFromHap(info.params[0], len, buffer);
267 if (state >= GLOBAL_ERROR || state < 0) {
268 ROSEN_LOGE("JsTool::Failed to get Rawfile buffer");
269 return false;
270 }
271 return true;
272 }
273
GetColorNumberResult(uint32_t origin)274 uint32_t JsTool::GetColorNumberResult(uint32_t origin)
275 {
276 uint32_t result = origin;
277 if ((origin >> COLOR_OFFSET_ALPHA) == 0) {
278 result = origin | COLOR_DEFAULT_ALPHA;
279 }
280 return result;
281 }
282
FastCheckColorType(const std::string & colorStr,const std::string & expectPrefix,const std::vector<size_t> & expectLengths)283 bool JsTool::FastCheckColorType(const std::string& colorStr, const std::string& expectPrefix,
284 const std::vector<size_t>& expectLengths)
285 {
286 // Check whether the beginning of colorStr is expectPrefix
287 // and whether the length of colorStr is in expectLengths.
288 if (colorStr.rfind(expectPrefix, 0) != 0) {
289 return false;
290 }
291 // if expectLengths is null that we do not check length.
292 if (expectLengths.size() == 0) {
293 return true;
294 }
295 return std::find(expectLengths.begin(), expectLengths.end(), colorStr.size()) != expectLengths.end();
296 }
297
HandleIncorrectColor(const std::string & newColorStr)298 uint32_t JsTool::HandleIncorrectColor(const std::string& newColorStr)
299 {
300 errno = 0;
301 char* end = nullptr;
302 uint32_t value = strtoul(newColorStr.c_str(), &end, COLOR_STRING_FORMAT);
303 if (errno == ERANGE) {
304 ROSEN_LOGE("JsTool::HandleIncorrectColor %{public}s is out of range.", newColorStr.c_str());
305 }
306 if (value == 0 && end == newColorStr.c_str()) {
307 ROSEN_LOGE("JsTool::HandleIncorrectColor input can not be converted to number, use default :0x0");
308 }
309 return value;
310 }
311
HandleRGBValue(int value,int & result)312 bool JsTool::HandleRGBValue(int value, int& result)
313 {
314 if (value < 0) {
315 return false;
316 }
317 result = value > Color::RGB_MAX ? Color::RGB_MAX : value;
318 return true;
319 }
320
IsOpacityValid(double value)321 bool JsTool::IsOpacityValid(double value)
322 {
323 return value >= 0 && value <= 1.0;
324 }
325
MatchColorWithMagic(std::string & colorStr,uint32_t & result)326 bool JsTool::MatchColorWithMagic(std::string& colorStr, uint32_t& result)
327 {
328 // This function we match string like "#FF0000" or "#FF0000FF" to get hexnumber
329 // Check whether the beginning of the string is "#" and whether the length of the string is vaild.
330 if (!FastCheckColorType(colorStr, "#", EXPECT_MAGIC_COLOR_LENGTHS)) {
331 ROSEN_LOGE("JsTool::MatchColorWithMagic colorString is invalid");
332 return false;
333 }
334 // Remove "#"
335 colorStr.erase(0, 1);
336
337 // Check whether the remaining part of the string is hexnumber
338 if (!std::regex_match(colorStr, HEX_PATTERN)) {
339 ROSEN_LOGE("JsTool::MatchColorWithMagic colorString is invalid hexnub");
340 return false;
341 }
342
343 result = HandleIncorrectColor(colorStr);
344 // If string is "#FF0000" that has not Alpha, set Alpha is "FF"
345 if (colorStr.length() < COLOR_STRING_SIZE_STANDARD) {
346 result |= COLOR_DEFAULT_ALPHA;
347 }
348 return true;
349 }
350
MatchColorWithMagicMini(std::string & colorStr,uint32_t & result)351 bool JsTool::MatchColorWithMagicMini(std::string& colorStr, uint32_t& result)
352 {
353 // This function we match string like "#FF0000" or "#FF0000FF" to get hexnumber
354 // Check whether the beginning of the string is "#" and whether the length of the string is vaild.
355 if (!FastCheckColorType(colorStr, "#", EXPECT_MAGIC_MINI_COLOR_LENGTHS)) {
356 ROSEN_LOGE("JsTool::MatchColorWithMagicMini colorString is invalid");
357 return false;
358 }
359 // Remove "#"
360 colorStr.erase(0, 1);
361
362 // Check whether the remaining part of the string is hexnumber
363 if (!std::regex_match(colorStr, HEX_PATTERN)) {
364 ROSEN_LOGE("JsTool::MatchColorWithMagicMini colorString is invalid hexnub");
365 return false;
366 }
367
368 // "#F00" is the abbreviation of "#FF0000", every will be used twice to make origin string
369 std::string newColorStr;
370 for (auto& c : colorStr) {
371 newColorStr += c;
372 newColorStr += c;
373 }
374 result = HandleIncorrectColor(newColorStr);
375 // If string is "#FF0000" that has not Alpha, set Alpha is "FF"
376 if (newColorStr.length() < COLOR_STRING_SIZE_STANDARD) {
377 result |= COLOR_DEFAULT_ALPHA;
378 }
379 return true;
380 }
381
MatchColorWithRGB(const std::string & colorStr,uint32_t & result)382 bool JsTool::MatchColorWithRGB(const std::string& colorStr, uint32_t& result)
383 {
384 // This function we match string like "rgb(255,0,0)" to get hexnumber
385 // Check whether the beginning of the string is "rgb(".
386 if (!FastCheckColorType(colorStr, "rgb(", {})) {
387 ROSEN_LOGE("JsTool::MatchColorWithRGB colorString is invalid");
388 return false;
389 }
390
391 // Using regular expressions to obtain the value of RGB
392 std::smatch matches;
393 if (std::regex_match(colorStr, matches, COLOR_WITH_RGB) && matches.size() == RGB_SUB_MATCH_SIZE) {
394 int redInt = 0;
395 int greenInt = 0;
396 int blueInt = 0;
397 if (!HandleRGBValue(std::stoi(matches[ARGC_ONE]), redInt) ||
398 !HandleRGBValue(std::stoi(matches[ARGC_TWO]), greenInt) ||
399 !HandleRGBValue(std::stoi(matches[ARGC_THREE]), blueInt)) {
400 ROSEN_LOGE("JsTool::MatchColorWithRGB colorStringNub is invalid");
401 return false;
402 }
403
404 auto red = static_cast<uint8_t>(redInt);
405 auto green = static_cast<uint8_t>(greenInt);
406 auto blue = static_cast<uint8_t>(blueInt);
407 result = COLOR_DEFAULT_ALPHA | (red << COLOR_OFFSET_RED) | (green << COLOR_OFFSET_GREEN) | blue;
408 return true;
409 }
410 return false;
411 }
412
MatchColorWithRGBA(const std::string & colorStr,uint32_t & result)413 bool JsTool::MatchColorWithRGBA(const std::string& colorStr, uint32_t& result)
414 {
415 // This function we match string like "rgba(255,0,0,0.5)" to get hexnumber
416 // Check whether the beginning of the string is "rgba(".
417 if (!FastCheckColorType(colorStr, "rgba(", {})) {
418 ROSEN_LOGE("JsTool::MatchColorWithRGBA colorString is invalid");
419 return false;
420 }
421
422 // Using regular expressions to obtain the value of RGBA
423 std::smatch matches;
424 if (std::regex_match(colorStr, matches, COLOR_WITH_RGBA) && matches.size() == RGBA_SUB_MATCH_SIZE) {
425 int redInt = 0;
426 int greenInt = 0;
427 int blueInt = 0;
428 auto opacityDouble = std::stod(matches[ARGC_FOUR]);
429 if (!HandleRGBValue(std::stoi(matches[ARGC_ONE]), redInt) ||
430 !HandleRGBValue(std::stoi(matches[ARGC_TWO]), greenInt) ||
431 !HandleRGBValue(std::stoi(matches[ARGC_THREE]), blueInt) ||
432 !IsOpacityValid(opacityDouble)) {
433 ROSEN_LOGE("JsTool::MatchColorWithRGBA colorStringNub is invalid");
434 return false;
435 }
436
437 auto red = static_cast<uint8_t>(redInt);
438 auto green = static_cast<uint8_t>(greenInt);
439 auto blue = static_cast<uint8_t>(blueInt);
440 uint8_t alpha = static_cast<uint8_t>(round(static_cast<double>(opacityDouble) * 0xff));
441 result = (alpha << COLOR_OFFSET_ALPHA) | (red << COLOR_OFFSET_RED) | (green << COLOR_OFFSET_GREEN) | blue;
442 return true;
443 }
444 return false;
445 }
446
GetColorStringResult(std::string colorStr,uint32_t & result)447 bool JsTool::GetColorStringResult(std::string colorStr, uint32_t& result)
448 {
449 if (colorStr.empty()) {
450 ROSEN_LOGE("JsTool::GetColorStringResult string is empty");
451 return false;
452 }
453
454 // e.g: Remove ' ' that change "rgb(255, 0, 0)" to "rgb(255,0,0)"
455 colorStr.erase(std::remove(colorStr.begin(), colorStr.end(), ' '), colorStr.end());
456
457 return (MatchColorWithMagic(colorStr, result) || MatchColorWithMagicMini(colorStr, result) ||
458 MatchColorWithRGB(colorStr, result) || MatchColorWithRGBA(colorStr, result));
459 }
460
GetColorObjectResult(napi_env env,napi_value value,uint32_t & result)461 bool JsTool::GetColorObjectResult(napi_env env, napi_value value, uint32_t& result)
462 {
463 ResourceInfo info;
464 if (!GetResourceInfo(env, value, info)) {
465 ROSEN_LOGE("JsTool::GetColorObjectResult GetResourceInfo failed!");
466 return false;
467 }
468
469 auto resourceManager = GetResourceManager();
470 if (resourceManager == nullptr) {
471 ROSEN_LOGE("JsTool::GetColorObjectResult resourceManager is nullptr!");
472 return false;
473 }
474
475 if (info.type == static_cast<int32_t>(ResourceType::STRING)) {
476 std::string colorStr = "";
477 int32_t state = resourceManager->GetStringById(static_cast<uint32_t>(info.resId), colorStr);
478 if (state >= GLOBAL_ERROR || state < 0) {
479 ROSEN_LOGE("JsTool::GetColorObjectResult failed to get colorString!");
480 return false;
481 }
482 if (!GetColorStringResult(colorStr, result)) {
483 ROSEN_LOGE("JsTool::GetColorObjectResult failed to GetColorStringResult!");
484 return false;
485 }
486 } else if (info.type == static_cast<int32_t>(ResourceType::INTEGER)) {
487 int colorResult = 0;
488 int32_t state = resourceManager->GetIntegerById(static_cast<uint32_t>(info.resId), colorResult);
489 if (state >= GLOBAL_ERROR || state < 0) {
490 ROSEN_LOGE("JsTool::GetColorObjectResult failed to get colorInt!");
491 return false;
492 }
493 result = GetColorNumberResult(colorResult);
494 } else if (info.type == static_cast<int32_t>(ResourceType::COLOR)) {
495 int32_t state = resourceManager->GetColorById(static_cast<uint32_t>(info.resId), result);
496 if (state >= GLOBAL_ERROR || state < 0) {
497 ROSEN_LOGE("JsTool::GetColorObjectResult failed to get colorColor!");
498 return false;
499 }
500 } else {
501 ROSEN_LOGE("JsTool::GetColorObjectResult invalid Resource type!");
502 return false;
503 }
504 return true;
505 }
506
GetResourceColor(napi_env env,napi_value res,uint32_t & result)507 bool JsTool::GetResourceColor(napi_env env, napi_value res, uint32_t& result)
508 {
509 napi_valuetype valueType = napi_undefined;
510 napi_typeof(env, res, &valueType);
511 if (valueType == napi_string) {
512 size_t len = 0;
513 napi_get_value_string_utf8(env, res, nullptr, 0, &len);
514 char* str = new(std::nothrow) char[len + 1];
515 if (!str) {
516 ROSEN_LOGE("JsTool::GetResourceColor memory is insufficient and failed to apply");
517 return false;
518 }
519 napi_get_value_string_utf8(env, res, str, len + 1, &len);
520 std::string colorStr(str, len);
521 delete[] str;
522 if (!GetColorStringResult(colorStr, result)) {
523 ROSEN_LOGE("JsTool::GetResourceColor failed to GetColorStringResult!");
524 return false;
525 }
526 } else if (valueType == napi_number) {
527 uint32_t colorNumber = 0;
528 napi_get_value_uint32(env, res, &colorNumber);
529 result = GetColorNumberResult(colorNumber);
530 } else if (valueType == napi_object) {
531 if (!GetColorObjectResult(env, res, result)) {
532 ROSEN_LOGE("JsTool::GetResourceColor failed to GetColorObjectResult!");
533 return false;
534 }
535 } else {
536 ROSEN_LOGE("JsTool::GetResourceColor invalid ResourceColor type!");
537 return false;
538 }
539 return true;
540 }
541 #endif
542 } // namespace Drawing
543 } // namespace OHOS::Rosen