base_type_conversion.cc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/base/metadata/base_type_conversion.h"
  5. #include <cmath>
  6. #include <string>
  7. #include "base/containers/fixed_flat_set.h"
  8. #include "base/cxx17_backports.h"
  9. #include "base/no_destructor.h"
  10. #include "base/strings/string_number_conversions.h"
  11. #include "base/strings/string_split.h"
  12. #include "base/strings/string_tokenizer.h"
  13. #include "base/strings/string_util.h"
  14. #include "base/strings/stringprintf.h"
  15. #include "base/strings/sys_string_conversions.h"
  16. #include "base/strings/utf_string_conversions.h"
  17. #include "base/time/time_delta_from_string.h"
  18. #include "third_party/abseil-cpp/absl/types/optional.h"
  19. #include "third_party/skia/include/core/SkScalar.h"
  20. #include "ui/gfx/color_utils.h"
  21. #include "ui/gfx/geometry/rect.h"
  22. namespace ui {
  23. namespace metadata {
  24. const char kNoPrefix[] = "";
  25. const char kSkColorPrefix[] = "--";
  26. std::u16string PointerToString(const void* pointer_val) {
  27. return pointer_val ? u"(assigned)" : u"(not assigned)";
  28. }
  29. const std::u16string& GetNullOptStr() {
  30. static const base::NoDestructor<std::u16string> kNullOptStr(u"<Empty>");
  31. return *kNullOptStr;
  32. }
  33. /***** String Conversions *****/
  34. #define CONVERT_NUMBER_TO_STRING(T) \
  35. std::u16string TypeConverter<T>::ToString(T source_value) { \
  36. return base::NumberToString16(source_value); \
  37. }
  38. CONVERT_NUMBER_TO_STRING(int8_t)
  39. CONVERT_NUMBER_TO_STRING(int16_t)
  40. CONVERT_NUMBER_TO_STRING(int32_t)
  41. CONVERT_NUMBER_TO_STRING(int64_t)
  42. CONVERT_NUMBER_TO_STRING(uint8_t)
  43. CONVERT_NUMBER_TO_STRING(uint16_t)
  44. CONVERT_NUMBER_TO_STRING(uint32_t)
  45. CONVERT_NUMBER_TO_STRING(uint64_t)
  46. CONVERT_NUMBER_TO_STRING(float)
  47. CONVERT_NUMBER_TO_STRING(double)
  48. std::u16string TypeConverter<bool>::ToString(bool source_value) {
  49. return source_value ? u"true" : u"false";
  50. }
  51. ValidStrings TypeConverter<bool>::GetValidStrings() {
  52. return {u"false", u"true"};
  53. }
  54. std::u16string TypeConverter<const char*>::ToString(const char* source_value) {
  55. return base::UTF8ToUTF16(source_value);
  56. }
  57. std::u16string TypeConverter<base::FilePath>::ToString(
  58. const base::FilePath& source_value) {
  59. return source_value.AsUTF16Unsafe();
  60. }
  61. std::u16string TypeConverter<std::u16string>::ToString(
  62. const std::u16string& source_value) {
  63. return source_value;
  64. }
  65. std::u16string TypeConverter<base::TimeDelta>::ToString(
  66. const base::TimeDelta& source_value) {
  67. return base::NumberToString16(source_value.InSecondsF()) + u"s";
  68. }
  69. std::u16string TypeConverter<gfx::Insets>::ToString(
  70. const gfx::Insets& source_value) {
  71. // This is different from gfx::Insets::ToString().
  72. return base::ASCIIToUTF16(
  73. base::StringPrintf("%d,%d,%d,%d", source_value.top(), source_value.left(),
  74. source_value.bottom(), source_value.right()));
  75. }
  76. std::u16string TypeConverter<gfx::Point>::ToString(
  77. const gfx::Point& source_value) {
  78. return base::ASCIIToUTF16(source_value.ToString());
  79. }
  80. std::u16string TypeConverter<gfx::PointF>::ToString(
  81. const gfx::PointF& source_value) {
  82. return base::ASCIIToUTF16(source_value.ToString());
  83. }
  84. std::u16string TypeConverter<gfx::Range>::ToString(
  85. const gfx::Range& source_value) {
  86. return base::ASCIIToUTF16(source_value.ToString());
  87. }
  88. std::u16string TypeConverter<gfx::Rect>::ToString(
  89. const gfx::Rect& source_value) {
  90. return base::ASCIIToUTF16(source_value.ToString());
  91. }
  92. std::u16string TypeConverter<gfx::RectF>::ToString(
  93. const gfx::RectF& source_value) {
  94. return base::ASCIIToUTF16(source_value.ToString());
  95. }
  96. std::u16string TypeConverter<gfx::ShadowValues>::ToString(
  97. const gfx::ShadowValues& source_value) {
  98. std::u16string ret = u"[";
  99. for (auto shadow_value : source_value) {
  100. ret += u" " + base::ASCIIToUTF16(shadow_value.ToString()) + u";";
  101. }
  102. ret[ret.length() - 1] = ' ';
  103. ret += u"]";
  104. return ret;
  105. }
  106. std::u16string TypeConverter<gfx::Size>::ToString(
  107. const gfx::Size& source_value) {
  108. return base::ASCIIToUTF16(source_value.ToString());
  109. }
  110. std::u16string TypeConverter<gfx::SizeF>::ToString(
  111. const gfx::SizeF& source_value) {
  112. return base::ASCIIToUTF16(source_value.ToString());
  113. }
  114. std::u16string TypeConverter<std::string>::ToString(
  115. const std::string& source_value) {
  116. return base::UTF8ToUTF16(source_value);
  117. }
  118. std::u16string TypeConverter<url::Component>::ToString(
  119. const url::Component& source_value) {
  120. return base::ASCIIToUTF16(
  121. base::StringPrintf("{%d,%d}", source_value.begin, source_value.len));
  122. }
  123. absl::optional<int8_t> TypeConverter<int8_t>::FromString(
  124. const std::u16string& source_value) {
  125. int32_t ret = 0;
  126. if (base::StringToInt(source_value, &ret) &&
  127. base::IsValueInRangeForNumericType<int8_t>(ret)) {
  128. return static_cast<int8_t>(ret);
  129. }
  130. return absl::nullopt;
  131. }
  132. absl::optional<int16_t> TypeConverter<int16_t>::FromString(
  133. const std::u16string& source_value) {
  134. int32_t ret = 0;
  135. if (base::StringToInt(source_value, &ret) &&
  136. base::IsValueInRangeForNumericType<int16_t>(ret)) {
  137. return static_cast<int16_t>(ret);
  138. }
  139. return absl::nullopt;
  140. }
  141. absl::optional<int32_t> TypeConverter<int32_t>::FromString(
  142. const std::u16string& source_value) {
  143. int value;
  144. return base::StringToInt(source_value, &value) ? absl::make_optional(value)
  145. : absl::nullopt;
  146. }
  147. absl::optional<int64_t> TypeConverter<int64_t>::FromString(
  148. const std::u16string& source_value) {
  149. int64_t value;
  150. return base::StringToInt64(source_value, &value) ? absl::make_optional(value)
  151. : absl::nullopt;
  152. }
  153. absl::optional<uint8_t> TypeConverter<uint8_t>::FromString(
  154. const std::u16string& source_value) {
  155. unsigned ret = 0;
  156. if (base::StringToUint(source_value, &ret) &&
  157. base::IsValueInRangeForNumericType<uint8_t>(ret)) {
  158. return static_cast<uint8_t>(ret);
  159. }
  160. return absl::nullopt;
  161. }
  162. absl::optional<uint16_t> TypeConverter<uint16_t>::FromString(
  163. const std::u16string& source_value) {
  164. unsigned ret = 0;
  165. if (base::StringToUint(source_value, &ret) &&
  166. base::IsValueInRangeForNumericType<uint16_t>(ret)) {
  167. return static_cast<uint16_t>(ret);
  168. }
  169. return absl::nullopt;
  170. }
  171. absl::optional<uint32_t> TypeConverter<uint32_t>::FromString(
  172. const std::u16string& source_value) {
  173. unsigned value;
  174. return base::StringToUint(source_value, &value) ? absl::make_optional(value)
  175. : absl::nullopt;
  176. }
  177. absl::optional<uint64_t> TypeConverter<uint64_t>::FromString(
  178. const std::u16string& source_value) {
  179. uint64_t value;
  180. return base::StringToUint64(source_value, &value) ? absl::make_optional(value)
  181. : absl::nullopt;
  182. }
  183. absl::optional<float> TypeConverter<float>::FromString(
  184. const std::u16string& source_value) {
  185. if (absl::optional<double> temp =
  186. TypeConverter<double>::FromString(source_value))
  187. return static_cast<float>(temp.value());
  188. return absl::nullopt;
  189. }
  190. absl::optional<double> TypeConverter<double>::FromString(
  191. const std::u16string& source_value) {
  192. double value;
  193. return base::StringToDouble(base::UTF16ToUTF8(source_value), &value)
  194. ? absl::make_optional(value)
  195. : absl::nullopt;
  196. }
  197. absl::optional<bool> TypeConverter<bool>::FromString(
  198. const std::u16string& source_value) {
  199. const bool is_true = source_value == u"true";
  200. if (is_true || source_value == u"false")
  201. return is_true;
  202. return absl::nullopt;
  203. }
  204. absl::optional<std::u16string> TypeConverter<std::u16string>::FromString(
  205. const std::u16string& source_value) {
  206. return source_value;
  207. }
  208. absl::optional<base::FilePath> TypeConverter<base::FilePath>::FromString(
  209. const std::u16string& source_value) {
  210. return base::FilePath::FromUTF16Unsafe(source_value);
  211. }
  212. absl::optional<base::TimeDelta> TypeConverter<base::TimeDelta>::FromString(
  213. const std::u16string& source_value) {
  214. std::string source = base::UTF16ToUTF8(source_value);
  215. return base::TimeDeltaFromString(source);
  216. }
  217. absl::optional<gfx::Insets> TypeConverter<gfx::Insets>::FromString(
  218. const std::u16string& source_value) {
  219. const auto values = base::SplitStringPiece(
  220. source_value, u",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  221. int top, left, bottom, right;
  222. if ((values.size() == 4) && base::StringToInt(values[0], &top) &&
  223. base::StringToInt(values[1], &left) &&
  224. base::StringToInt(values[2], &bottom) &&
  225. base::StringToInt(values[3], &right)) {
  226. return gfx::Insets::TLBR(top, left, bottom, right);
  227. }
  228. return absl::nullopt;
  229. }
  230. absl::optional<gfx::Point> TypeConverter<gfx::Point>::FromString(
  231. const std::u16string& source_value) {
  232. const auto values = base::SplitStringPiece(
  233. source_value, u",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  234. int x, y;
  235. if ((values.size() == 2) && base::StringToInt(values[0], &x) &&
  236. base::StringToInt(values[1], &y)) {
  237. return gfx::Point(x, y);
  238. }
  239. return absl::nullopt;
  240. }
  241. absl::optional<gfx::PointF> TypeConverter<gfx::PointF>::FromString(
  242. const std::u16string& source_value) {
  243. const auto values = base::SplitStringPiece(
  244. source_value, u",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  245. double x, y;
  246. if ((values.size() == 2) && base::StringToDouble(values[0], &x) &&
  247. base::StringToDouble(values[1], &y)) {
  248. return gfx::PointF(x, y);
  249. }
  250. return absl::nullopt;
  251. }
  252. absl::optional<gfx::Range> TypeConverter<gfx::Range>::FromString(
  253. const std::u16string& source_value) {
  254. const auto values = base::SplitStringPiece(
  255. source_value, u"{,}", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  256. unsigned min, max;
  257. if ((values.size() == 2) && base::StringToUint(values[0], &min) &&
  258. base::StringToUint(values[1], &max)) {
  259. return gfx::Range(min, max);
  260. }
  261. return absl::nullopt;
  262. }
  263. absl::optional<gfx::Rect> TypeConverter<gfx::Rect>::FromString(
  264. const std::u16string& source_value) {
  265. const auto values = base::SplitString(
  266. source_value, u" ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  267. if (values.size() != 2)
  268. return absl::nullopt;
  269. const absl::optional<gfx::Point> origin =
  270. TypeConverter<gfx::Point>::FromString(values[0]);
  271. const absl::optional<gfx::Size> size =
  272. TypeConverter<gfx::Size>::FromString(values[1]);
  273. if (origin && size)
  274. return gfx::Rect(*origin, *size);
  275. return absl::nullopt;
  276. }
  277. absl::optional<gfx::RectF> TypeConverter<gfx::RectF>::FromString(
  278. const std::u16string& source_value) {
  279. const auto values = base::SplitString(
  280. source_value, u" ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  281. if (values.size() != 2)
  282. return absl::nullopt;
  283. const absl::optional<gfx::PointF> origin =
  284. TypeConverter<gfx::PointF>::FromString(values[0]);
  285. const absl::optional<gfx::SizeF> size =
  286. TypeConverter<gfx::SizeF>::FromString(values[1]);
  287. if (origin && size)
  288. return gfx::RectF(*origin, *size);
  289. return absl::nullopt;
  290. }
  291. absl::optional<gfx::ShadowValues> TypeConverter<gfx::ShadowValues>::FromString(
  292. const std::u16string& source_value) {
  293. gfx::ShadowValues ret;
  294. const auto shadow_value_strings = base::SplitStringPiece(
  295. source_value, u"[;]", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  296. for (auto v : shadow_value_strings) {
  297. std::u16string value = std::u16string(v);
  298. base::String16Tokenizer tokenizer(
  299. value, u"(,)", base::String16Tokenizer::WhitespacePolicy::kSkipOver);
  300. tokenizer.set_options(base::String16Tokenizer::RETURN_DELIMS);
  301. int x, y;
  302. double blur;
  303. if (tokenizer.GetNext() && tokenizer.token_piece() == u"(" &&
  304. tokenizer.GetNext() && base::StringToInt(tokenizer.token_piece(), &x) &&
  305. tokenizer.GetNext() && tokenizer.token_piece() == u"," &&
  306. tokenizer.GetNext() && base::StringToInt(tokenizer.token_piece(), &y) &&
  307. tokenizer.GetNext() && tokenizer.token_piece() == u")" &&
  308. tokenizer.GetNext() && tokenizer.token_piece() == u"," &&
  309. tokenizer.GetNext() &&
  310. base::StringToDouble(tokenizer.token_piece(), &blur) &&
  311. tokenizer.GetNext() && tokenizer.token_piece() == u"," &&
  312. tokenizer.GetNext()) {
  313. const auto color =
  314. SkColorConverter::GetNextColor(tokenizer.token_begin(), value.cend());
  315. if (color)
  316. ret.emplace_back(gfx::Vector2d(x, y), blur, color.value());
  317. }
  318. }
  319. return ret;
  320. }
  321. absl::optional<gfx::Size> TypeConverter<gfx::Size>::FromString(
  322. const std::u16string& source_value) {
  323. const auto values = base::SplitStringPiece(
  324. source_value, u"x", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  325. int width, height;
  326. if ((values.size() == 2) && base::StringToInt(values[0], &width) &&
  327. base::StringToInt(values[1], &height)) {
  328. return gfx::Size(width, height);
  329. }
  330. return absl::nullopt;
  331. }
  332. absl::optional<gfx::SizeF> TypeConverter<gfx::SizeF>::FromString(
  333. const std::u16string& source_value) {
  334. const auto values = base::SplitStringPiece(
  335. source_value, u"x", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  336. double width, height;
  337. if ((values.size() == 2) && base::StringToDouble(values[0], &width) &&
  338. base::StringToDouble(values[1], &height)) {
  339. return gfx::SizeF(width, height);
  340. }
  341. return absl::nullopt;
  342. }
  343. absl::optional<std::string> TypeConverter<std::string>::FromString(
  344. const std::u16string& source_value) {
  345. return base::UTF16ToUTF8(source_value);
  346. }
  347. absl::optional<url::Component> TypeConverter<url::Component>::FromString(
  348. const std::u16string& source_value) {
  349. const auto values = base::SplitStringPiece(
  350. source_value, u"{,}", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  351. int begin, len;
  352. if ((values.size() == 2) && base::StringToInt(values[0], &begin) &&
  353. base::StringToInt(values[1], &len) && len >= -1) {
  354. return url::Component(begin, len);
  355. }
  356. return absl::nullopt;
  357. }
  358. std::u16string TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::ToString(
  359. SkColor source_value) {
  360. return base::UTF8ToUTF16(color_utils::SkColorToRgbaString(source_value));
  361. }
  362. absl::optional<SkColor> TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::FromString(
  363. const std::u16string& source_value) {
  364. return GetNextColor(source_value.cbegin(), source_value.cend());
  365. }
  366. ValidStrings TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetValidStrings() {
  367. return {};
  368. }
  369. bool TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetNextColor(
  370. std::u16string::const_iterator start,
  371. std::u16string::const_iterator end,
  372. std::u16string& color,
  373. std::u16string::const_iterator& next_token) {
  374. static const auto open_paren = u'(';
  375. static const auto close_paren = u')';
  376. static constexpr auto schemes = base::MakeFixedFlatSet<base::StringPiece16>(
  377. {u"hsl", u"hsla", u"rgb", u"rgba"});
  378. base::String16Tokenizer tokenizer(
  379. start, end, u"(,)", base::String16Tokenizer::WhitespacePolicy::kSkipOver);
  380. tokenizer.set_options(base::String16Tokenizer::RETURN_DELIMS);
  381. for (; tokenizer.GetNext();) {
  382. if (!tokenizer.token_is_delim()) {
  383. base::StringPiece16 token = tokenizer.token_piece();
  384. std::u16string::const_iterator start_color = tokenizer.token_begin();
  385. if (base::ranges::find(schemes.begin(), schemes.end(), token) !=
  386. schemes.end()) {
  387. if (!tokenizer.GetNext() || *tokenizer.token_begin() != open_paren)
  388. return false;
  389. for (;
  390. tokenizer.GetNext() && *tokenizer.token_begin() != close_paren;) {
  391. }
  392. if (*tokenizer.token_begin() != close_paren)
  393. return false;
  394. }
  395. next_token = tokenizer.token_end();
  396. color = std::u16string(start_color, next_token);
  397. return true;
  398. }
  399. }
  400. return false;
  401. }
  402. bool TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetNextColor(
  403. std::u16string::const_iterator start,
  404. std::u16string::const_iterator end,
  405. std::u16string& color) {
  406. std::u16string::const_iterator next_token;
  407. return GetNextColor(start, end, color, next_token);
  408. }
  409. absl::optional<SkColor> TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetNextColor(
  410. std::u16string::const_iterator start,
  411. std::u16string::const_iterator end,
  412. std::u16string::const_iterator& next_token) {
  413. std::u16string color;
  414. if (GetNextColor(start, end, color, next_token)) {
  415. if (base::StartsWith(color, u"hsl", base::CompareCase::SENSITIVE))
  416. return ParseHslString(color);
  417. if (base::StartsWith(color, u"rgb", base::CompareCase::SENSITIVE))
  418. return ParseRgbString(color);
  419. if (base::StartsWith(color, u"0x", base::CompareCase::INSENSITIVE_ASCII))
  420. return ParseHexString(color);
  421. SkColor value;
  422. if (base::StringToUint(color, &value))
  423. return absl::make_optional(value);
  424. }
  425. return absl::nullopt;
  426. }
  427. absl::optional<SkColor> TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetNextColor(
  428. std::u16string::const_iterator start,
  429. std::u16string::const_iterator end) {
  430. std::u16string::const_iterator next_token;
  431. return GetNextColor(start, end, next_token);
  432. }
  433. absl::optional<SkColor>
  434. TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::RgbaPiecesToSkColor(
  435. const std::vector<base::StringPiece16>& pieces,
  436. size_t start_piece) {
  437. int r, g, b;
  438. double a;
  439. return ((pieces.size() >= start_piece + 4) &&
  440. base::StringToInt(pieces[start_piece], &r) &&
  441. base::IsValueInRangeForNumericType<uint8_t>(r) &&
  442. base::StringToInt(pieces[start_piece + 1], &g) &&
  443. base::IsValueInRangeForNumericType<uint8_t>(g) &&
  444. base::StringToInt(pieces[start_piece + 2], &b) &&
  445. base::IsValueInRangeForNumericType<uint8_t>(b) &&
  446. base::StringToDouble(pieces[start_piece + 3], &a) && a >= 0.0 &&
  447. a <= 1.0)
  448. ? absl::make_optional(SkColorSetARGB(
  449. base::ClampRound<SkAlpha>(a * SK_AlphaOPAQUE), r, g, b))
  450. : absl::nullopt;
  451. }
  452. absl::optional<SkColor>
  453. TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::ParseHexString(
  454. const std::u16string& hex_string) {
  455. SkColor value;
  456. if (base::HexStringToUInt(base::UTF16ToUTF8(hex_string), &value)) {
  457. // Add in a 1.0 alpha channel if it wasn't included in the input.
  458. if (hex_string.length() <= 8)
  459. value = SkColorSetA(value, 0xFF);
  460. return absl::make_optional(value);
  461. }
  462. return absl::nullopt;
  463. }
  464. absl::optional<SkColor>
  465. TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::ParseHslString(
  466. const std::u16string& hsl_string) {
  467. std::u16string pruned_string;
  468. base::RemoveChars(hsl_string, u"(%)hsla", &pruned_string);
  469. const auto values = base::SplitStringPiece(
  470. pruned_string, u", ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  471. double h, s, v;
  472. double a = 1.0;
  473. if (values.size() >= 3 && values.size() <= 4 &&
  474. base::StringToDouble(values[0], &h) &&
  475. base::StringToDouble(values[1], &s) &&
  476. base::StringToDouble(values[2], &v) &&
  477. (values.size() == 3 ||
  478. (base::StringToDouble(values[3], &a) && a >= 0.0 && a <= 1.0))) {
  479. SkScalar hsv[3];
  480. hsv[0] = base::clamp(std::fmod(h, 360.0), 0.0, 360.0);
  481. hsv[1] =
  482. s > 1.0 ? base::clamp(s, 0.0, 100.0) / 100.0 : base::clamp(s, 0.0, 1.0);
  483. hsv[2] =
  484. v > 1.0 ? base::clamp(v, 0.0, 100.0) / 100.0 : base::clamp(v, 0.0, 1.0);
  485. return absl::make_optional(
  486. SkHSVToColor(base::ClampRound<SkAlpha>(a * SK_AlphaOPAQUE), hsv));
  487. }
  488. return absl::nullopt;
  489. }
  490. absl::optional<SkColor>
  491. TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::ParseRgbString(
  492. const std::u16string& rgb_string) {
  493. // Declare a constant string here for use below since it might trigger an
  494. // ASAN error due to the stack temp going out of scope before the call to
  495. // RgbaPiecesToSkColor.
  496. std::u16string pruned_string;
  497. base::RemoveChars(rgb_string, u"()rgba", &pruned_string);
  498. auto values = base::SplitStringPiece(
  499. pruned_string, u", ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  500. // if it was just an rgb string, add the 1.0 alpha
  501. if (values.size() == 3)
  502. values.push_back(u"1.0");
  503. return RgbaPiecesToSkColor(values, 0);
  504. }
  505. } // namespace metadata
  506. } // namespace ui
  507. DEFINE_ENUM_CONVERTERS(gfx::HorizontalAlignment,
  508. {gfx::HorizontalAlignment::ALIGN_LEFT, u"ALIGN_LEFT"},
  509. {gfx::HorizontalAlignment::ALIGN_CENTER,
  510. u"ALIGN_CENTER"},
  511. {gfx::HorizontalAlignment::ALIGN_RIGHT, u"ALIGN_RIGHT"},
  512. {gfx::HorizontalAlignment::ALIGN_TO_HEAD,
  513. u"ALIGN_TO_HEAD"})
  514. DEFINE_ENUM_CONVERTERS(gfx::VerticalAlignment,
  515. {gfx::VerticalAlignment::ALIGN_TOP, u"ALIGN_TOP"},
  516. {gfx::VerticalAlignment::ALIGN_MIDDLE, u"ALIGN_MIDDLE"},
  517. {gfx::VerticalAlignment::ALIGN_BOTTOM, u"ALIGN_BOTTOM"})
  518. DEFINE_ENUM_CONVERTERS(gfx::ElideBehavior,
  519. {gfx::ElideBehavior::NO_ELIDE, u"NO_ELIDE"},
  520. {gfx::ElideBehavior::TRUNCATE, u"TRUNCATE"},
  521. {gfx::ElideBehavior::ELIDE_HEAD, u"ELIDE_HEAD"},
  522. {gfx::ElideBehavior::ELIDE_MIDDLE, u"ELIDE_MIDDLE"},
  523. {gfx::ElideBehavior::ELIDE_TAIL, u"ELIDE_TAIL"},
  524. {gfx::ElideBehavior::ELIDE_EMAIL, u"ELIDE_EMAIL"},
  525. {gfx::ElideBehavior::FADE_TAIL, u"FADE_TAIL"})
  526. DEFINE_ENUM_CONVERTERS(
  527. ui::MenuSeparatorType,
  528. {ui::MenuSeparatorType::NORMAL_SEPARATOR, u"NORMAL_SEPARATOR"},
  529. {ui::MenuSeparatorType::DOUBLE_SEPARATOR, u"DOUBLE_SEPARATOR"},
  530. {ui::MenuSeparatorType::UPPER_SEPARATOR, u"UPPER_SEPARATOR"},
  531. {ui::MenuSeparatorType::LOWER_SEPARATOR, u"LOWER_SEPARATOR"},
  532. {ui::MenuSeparatorType::SPACING_SEPARATOR, u"SPACING_SEPARATOR"},
  533. {ui::MenuSeparatorType::VERTICAL_SEPARATOR, u"VERTICAL_SEPARATOR"},
  534. {ui::MenuSeparatorType::PADDED_SEPARATOR, u"PADDED_SEPARATOR"})