| 277 | } |
| 278 | |
| 279 | Color parse(const ccstd::string &cssStr) { |
| 280 | ccstd::string str = cssStr; |
| 281 | |
| 282 | // Remove all whitespace, not compliant, but should just be more accepting. |
| 283 | str.erase(std::remove(str.begin(), str.end(), ' '), str.end()); |
| 284 | |
| 285 | // Convert to lowercase. |
| 286 | std::transform(str.begin(), str.end(), str.begin(), ::tolower); |
| 287 | |
| 288 | for (const auto &namedColor : NAMED_COLORS) { |
| 289 | if (str == namedColor.name) { |
| 290 | return namedColor.color; |
| 291 | } |
| 292 | } |
| 293 | |
| 294 | // #abc and #abc123 syntax. |
| 295 | if (str.length() && str.front() == '#') { |
| 296 | if (str.length() == 4) { |
| 297 | int64_t iv = |
| 298 | parseInt(str.substr(1), 16); // REFINE(deanm): Stricter parsing. |
| 299 | if (!(iv >= 0 && iv <= 0xfff)) { |
| 300 | return {}; |
| 301 | } |
| 302 | |
| 303 | return Color( |
| 304 | static_cast<uint8_t>(((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8)), |
| 305 | static_cast<uint8_t>((iv & 0xf0) | ((iv & 0xf0) >> 4)), |
| 306 | static_cast<uint8_t>((iv & 0xf) | ((iv & 0xf) << 4)), 1); |
| 307 | } |
| 308 | |
| 309 | if (str.length() == 7) { |
| 310 | int64_t iv = parseInt(str.substr(1), 16); // REFINE(deanm): Stricter parsing. |
| 311 | if (!(iv >= 0 && iv <= 0xffffff)) { |
| 312 | return {}; // Covers NaN. |
| 313 | } |
| 314 | |
| 315 | return Color(static_cast<uint8_t>((iv & 0xff0000) >> 16), |
| 316 | static_cast<uint8_t>((iv & 0xff00) >> 8), |
| 317 | static_cast<uint8_t>(iv & 0xff), 1); |
| 318 | } |
| 319 | |
| 320 | return Color(); |
| 321 | } |
| 322 | |
| 323 | size_t op = str.find_first_of('('); |
| 324 | size_t ep = str.find_first_of(')'); |
| 325 | if (op != ccstd::string::npos && ep + 1 == str.length()) { |
| 326 | const ccstd::string fname = str.substr(0, op); |
| 327 | const ccstd::vector<ccstd::string> params = |
| 328 | split(str.substr(op + 1, ep - (op + 1)), ','); |
| 329 | |
| 330 | float alpha = 1.0f; |
| 331 | |
| 332 | if (fname == "rgba" || fname == "rgb") { |
| 333 | if (fname == "rgba") { |
| 334 | if (params.size() != 4) { |
| 335 | return {}; |
| 336 | } |
no test coverage detected