123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ui/base/metadata/base_type_conversion.h"
- #include <cmath>
- #include <string>
- #include "base/containers/fixed_flat_set.h"
- #include "base/cxx17_backports.h"
- #include "base/no_destructor.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/strings/string_split.h"
- #include "base/strings/string_tokenizer.h"
- #include "base/strings/string_util.h"
- #include "base/strings/stringprintf.h"
- #include "base/strings/sys_string_conversions.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/time/time_delta_from_string.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "third_party/skia/include/core/SkScalar.h"
- #include "ui/gfx/color_utils.h"
- #include "ui/gfx/geometry/rect.h"
- namespace ui {
- namespace metadata {
- const char kNoPrefix[] = "";
- const char kSkColorPrefix[] = "--";
- std::u16string PointerToString(const void* pointer_val) {
- return pointer_val ? u"(assigned)" : u"(not assigned)";
- }
- const std::u16string& GetNullOptStr() {
- static const base::NoDestructor<std::u16string> kNullOptStr(u"<Empty>");
- return *kNullOptStr;
- }
- /***** String Conversions *****/
- #define CONVERT_NUMBER_TO_STRING(T) \
- std::u16string TypeConverter<T>::ToString(T source_value) { \
- return base::NumberToString16(source_value); \
- }
- CONVERT_NUMBER_TO_STRING(int8_t)
- CONVERT_NUMBER_TO_STRING(int16_t)
- CONVERT_NUMBER_TO_STRING(int32_t)
- CONVERT_NUMBER_TO_STRING(int64_t)
- CONVERT_NUMBER_TO_STRING(uint8_t)
- CONVERT_NUMBER_TO_STRING(uint16_t)
- CONVERT_NUMBER_TO_STRING(uint32_t)
- CONVERT_NUMBER_TO_STRING(uint64_t)
- CONVERT_NUMBER_TO_STRING(float)
- CONVERT_NUMBER_TO_STRING(double)
- std::u16string TypeConverter<bool>::ToString(bool source_value) {
- return source_value ? u"true" : u"false";
- }
- ValidStrings TypeConverter<bool>::GetValidStrings() {
- return {u"false", u"true"};
- }
- std::u16string TypeConverter<const char*>::ToString(const char* source_value) {
- return base::UTF8ToUTF16(source_value);
- }
- std::u16string TypeConverter<base::FilePath>::ToString(
- const base::FilePath& source_value) {
- return source_value.AsUTF16Unsafe();
- }
- std::u16string TypeConverter<std::u16string>::ToString(
- const std::u16string& source_value) {
- return source_value;
- }
- std::u16string TypeConverter<base::TimeDelta>::ToString(
- const base::TimeDelta& source_value) {
- return base::NumberToString16(source_value.InSecondsF()) + u"s";
- }
- std::u16string TypeConverter<gfx::Insets>::ToString(
- const gfx::Insets& source_value) {
- // This is different from gfx::Insets::ToString().
- return base::ASCIIToUTF16(
- base::StringPrintf("%d,%d,%d,%d", source_value.top(), source_value.left(),
- source_value.bottom(), source_value.right()));
- }
- std::u16string TypeConverter<gfx::Point>::ToString(
- const gfx::Point& source_value) {
- return base::ASCIIToUTF16(source_value.ToString());
- }
- std::u16string TypeConverter<gfx::PointF>::ToString(
- const gfx::PointF& source_value) {
- return base::ASCIIToUTF16(source_value.ToString());
- }
- std::u16string TypeConverter<gfx::Range>::ToString(
- const gfx::Range& source_value) {
- return base::ASCIIToUTF16(source_value.ToString());
- }
- std::u16string TypeConverter<gfx::Rect>::ToString(
- const gfx::Rect& source_value) {
- return base::ASCIIToUTF16(source_value.ToString());
- }
- std::u16string TypeConverter<gfx::RectF>::ToString(
- const gfx::RectF& source_value) {
- return base::ASCIIToUTF16(source_value.ToString());
- }
- std::u16string TypeConverter<gfx::ShadowValues>::ToString(
- const gfx::ShadowValues& source_value) {
- std::u16string ret = u"[";
- for (auto shadow_value : source_value) {
- ret += u" " + base::ASCIIToUTF16(shadow_value.ToString()) + u";";
- }
- ret[ret.length() - 1] = ' ';
- ret += u"]";
- return ret;
- }
- std::u16string TypeConverter<gfx::Size>::ToString(
- const gfx::Size& source_value) {
- return base::ASCIIToUTF16(source_value.ToString());
- }
- std::u16string TypeConverter<gfx::SizeF>::ToString(
- const gfx::SizeF& source_value) {
- return base::ASCIIToUTF16(source_value.ToString());
- }
- std::u16string TypeConverter<std::string>::ToString(
- const std::string& source_value) {
- return base::UTF8ToUTF16(source_value);
- }
- std::u16string TypeConverter<url::Component>::ToString(
- const url::Component& source_value) {
- return base::ASCIIToUTF16(
- base::StringPrintf("{%d,%d}", source_value.begin, source_value.len));
- }
- absl::optional<int8_t> TypeConverter<int8_t>::FromString(
- const std::u16string& source_value) {
- int32_t ret = 0;
- if (base::StringToInt(source_value, &ret) &&
- base::IsValueInRangeForNumericType<int8_t>(ret)) {
- return static_cast<int8_t>(ret);
- }
- return absl::nullopt;
- }
- absl::optional<int16_t> TypeConverter<int16_t>::FromString(
- const std::u16string& source_value) {
- int32_t ret = 0;
- if (base::StringToInt(source_value, &ret) &&
- base::IsValueInRangeForNumericType<int16_t>(ret)) {
- return static_cast<int16_t>(ret);
- }
- return absl::nullopt;
- }
- absl::optional<int32_t> TypeConverter<int32_t>::FromString(
- const std::u16string& source_value) {
- int value;
- return base::StringToInt(source_value, &value) ? absl::make_optional(value)
- : absl::nullopt;
- }
- absl::optional<int64_t> TypeConverter<int64_t>::FromString(
- const std::u16string& source_value) {
- int64_t value;
- return base::StringToInt64(source_value, &value) ? absl::make_optional(value)
- : absl::nullopt;
- }
- absl::optional<uint8_t> TypeConverter<uint8_t>::FromString(
- const std::u16string& source_value) {
- unsigned ret = 0;
- if (base::StringToUint(source_value, &ret) &&
- base::IsValueInRangeForNumericType<uint8_t>(ret)) {
- return static_cast<uint8_t>(ret);
- }
- return absl::nullopt;
- }
- absl::optional<uint16_t> TypeConverter<uint16_t>::FromString(
- const std::u16string& source_value) {
- unsigned ret = 0;
- if (base::StringToUint(source_value, &ret) &&
- base::IsValueInRangeForNumericType<uint16_t>(ret)) {
- return static_cast<uint16_t>(ret);
- }
- return absl::nullopt;
- }
- absl::optional<uint32_t> TypeConverter<uint32_t>::FromString(
- const std::u16string& source_value) {
- unsigned value;
- return base::StringToUint(source_value, &value) ? absl::make_optional(value)
- : absl::nullopt;
- }
- absl::optional<uint64_t> TypeConverter<uint64_t>::FromString(
- const std::u16string& source_value) {
- uint64_t value;
- return base::StringToUint64(source_value, &value) ? absl::make_optional(value)
- : absl::nullopt;
- }
- absl::optional<float> TypeConverter<float>::FromString(
- const std::u16string& source_value) {
- if (absl::optional<double> temp =
- TypeConverter<double>::FromString(source_value))
- return static_cast<float>(temp.value());
- return absl::nullopt;
- }
- absl::optional<double> TypeConverter<double>::FromString(
- const std::u16string& source_value) {
- double value;
- return base::StringToDouble(base::UTF16ToUTF8(source_value), &value)
- ? absl::make_optional(value)
- : absl::nullopt;
- }
- absl::optional<bool> TypeConverter<bool>::FromString(
- const std::u16string& source_value) {
- const bool is_true = source_value == u"true";
- if (is_true || source_value == u"false")
- return is_true;
- return absl::nullopt;
- }
- absl::optional<std::u16string> TypeConverter<std::u16string>::FromString(
- const std::u16string& source_value) {
- return source_value;
- }
- absl::optional<base::FilePath> TypeConverter<base::FilePath>::FromString(
- const std::u16string& source_value) {
- return base::FilePath::FromUTF16Unsafe(source_value);
- }
- absl::optional<base::TimeDelta> TypeConverter<base::TimeDelta>::FromString(
- const std::u16string& source_value) {
- std::string source = base::UTF16ToUTF8(source_value);
- return base::TimeDeltaFromString(source);
- }
- absl::optional<gfx::Insets> TypeConverter<gfx::Insets>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitStringPiece(
- source_value, u",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- int top, left, bottom, right;
- if ((values.size() == 4) && base::StringToInt(values[0], &top) &&
- base::StringToInt(values[1], &left) &&
- base::StringToInt(values[2], &bottom) &&
- base::StringToInt(values[3], &right)) {
- return gfx::Insets::TLBR(top, left, bottom, right);
- }
- return absl::nullopt;
- }
- absl::optional<gfx::Point> TypeConverter<gfx::Point>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitStringPiece(
- source_value, u",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- int x, y;
- if ((values.size() == 2) && base::StringToInt(values[0], &x) &&
- base::StringToInt(values[1], &y)) {
- return gfx::Point(x, y);
- }
- return absl::nullopt;
- }
- absl::optional<gfx::PointF> TypeConverter<gfx::PointF>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitStringPiece(
- source_value, u",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- double x, y;
- if ((values.size() == 2) && base::StringToDouble(values[0], &x) &&
- base::StringToDouble(values[1], &y)) {
- return gfx::PointF(x, y);
- }
- return absl::nullopt;
- }
- absl::optional<gfx::Range> TypeConverter<gfx::Range>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitStringPiece(
- source_value, u"{,}", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- unsigned min, max;
- if ((values.size() == 2) && base::StringToUint(values[0], &min) &&
- base::StringToUint(values[1], &max)) {
- return gfx::Range(min, max);
- }
- return absl::nullopt;
- }
- absl::optional<gfx::Rect> TypeConverter<gfx::Rect>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitString(
- source_value, u" ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- if (values.size() != 2)
- return absl::nullopt;
- const absl::optional<gfx::Point> origin =
- TypeConverter<gfx::Point>::FromString(values[0]);
- const absl::optional<gfx::Size> size =
- TypeConverter<gfx::Size>::FromString(values[1]);
- if (origin && size)
- return gfx::Rect(*origin, *size);
- return absl::nullopt;
- }
- absl::optional<gfx::RectF> TypeConverter<gfx::RectF>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitString(
- source_value, u" ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- if (values.size() != 2)
- return absl::nullopt;
- const absl::optional<gfx::PointF> origin =
- TypeConverter<gfx::PointF>::FromString(values[0]);
- const absl::optional<gfx::SizeF> size =
- TypeConverter<gfx::SizeF>::FromString(values[1]);
- if (origin && size)
- return gfx::RectF(*origin, *size);
- return absl::nullopt;
- }
- absl::optional<gfx::ShadowValues> TypeConverter<gfx::ShadowValues>::FromString(
- const std::u16string& source_value) {
- gfx::ShadowValues ret;
- const auto shadow_value_strings = base::SplitStringPiece(
- source_value, u"[;]", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- for (auto v : shadow_value_strings) {
- std::u16string value = std::u16string(v);
- base::String16Tokenizer tokenizer(
- value, u"(,)", base::String16Tokenizer::WhitespacePolicy::kSkipOver);
- tokenizer.set_options(base::String16Tokenizer::RETURN_DELIMS);
- int x, y;
- double blur;
- if (tokenizer.GetNext() && tokenizer.token_piece() == u"(" &&
- tokenizer.GetNext() && base::StringToInt(tokenizer.token_piece(), &x) &&
- tokenizer.GetNext() && tokenizer.token_piece() == u"," &&
- tokenizer.GetNext() && base::StringToInt(tokenizer.token_piece(), &y) &&
- tokenizer.GetNext() && tokenizer.token_piece() == u")" &&
- tokenizer.GetNext() && tokenizer.token_piece() == u"," &&
- tokenizer.GetNext() &&
- base::StringToDouble(tokenizer.token_piece(), &blur) &&
- tokenizer.GetNext() && tokenizer.token_piece() == u"," &&
- tokenizer.GetNext()) {
- const auto color =
- SkColorConverter::GetNextColor(tokenizer.token_begin(), value.cend());
- if (color)
- ret.emplace_back(gfx::Vector2d(x, y), blur, color.value());
- }
- }
- return ret;
- }
- absl::optional<gfx::Size> TypeConverter<gfx::Size>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitStringPiece(
- source_value, u"x", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- int width, height;
- if ((values.size() == 2) && base::StringToInt(values[0], &width) &&
- base::StringToInt(values[1], &height)) {
- return gfx::Size(width, height);
- }
- return absl::nullopt;
- }
- absl::optional<gfx::SizeF> TypeConverter<gfx::SizeF>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitStringPiece(
- source_value, u"x", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- double width, height;
- if ((values.size() == 2) && base::StringToDouble(values[0], &width) &&
- base::StringToDouble(values[1], &height)) {
- return gfx::SizeF(width, height);
- }
- return absl::nullopt;
- }
- absl::optional<std::string> TypeConverter<std::string>::FromString(
- const std::u16string& source_value) {
- return base::UTF16ToUTF8(source_value);
- }
- absl::optional<url::Component> TypeConverter<url::Component>::FromString(
- const std::u16string& source_value) {
- const auto values = base::SplitStringPiece(
- source_value, u"{,}", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- int begin, len;
- if ((values.size() == 2) && base::StringToInt(values[0], &begin) &&
- base::StringToInt(values[1], &len) && len >= -1) {
- return url::Component(begin, len);
- }
- return absl::nullopt;
- }
- std::u16string TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::ToString(
- SkColor source_value) {
- return base::UTF8ToUTF16(color_utils::SkColorToRgbaString(source_value));
- }
- absl::optional<SkColor> TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::FromString(
- const std::u16string& source_value) {
- return GetNextColor(source_value.cbegin(), source_value.cend());
- }
- ValidStrings TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetValidStrings() {
- return {};
- }
- bool TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetNextColor(
- std::u16string::const_iterator start,
- std::u16string::const_iterator end,
- std::u16string& color,
- std::u16string::const_iterator& next_token) {
- static const auto open_paren = u'(';
- static const auto close_paren = u')';
- static constexpr auto schemes = base::MakeFixedFlatSet<base::StringPiece16>(
- {u"hsl", u"hsla", u"rgb", u"rgba"});
- base::String16Tokenizer tokenizer(
- start, end, u"(,)", base::String16Tokenizer::WhitespacePolicy::kSkipOver);
- tokenizer.set_options(base::String16Tokenizer::RETURN_DELIMS);
- for (; tokenizer.GetNext();) {
- if (!tokenizer.token_is_delim()) {
- base::StringPiece16 token = tokenizer.token_piece();
- std::u16string::const_iterator start_color = tokenizer.token_begin();
- if (base::ranges::find(schemes.begin(), schemes.end(), token) !=
- schemes.end()) {
- if (!tokenizer.GetNext() || *tokenizer.token_begin() != open_paren)
- return false;
- for (;
- tokenizer.GetNext() && *tokenizer.token_begin() != close_paren;) {
- }
- if (*tokenizer.token_begin() != close_paren)
- return false;
- }
- next_token = tokenizer.token_end();
- color = std::u16string(start_color, next_token);
- return true;
- }
- }
- return false;
- }
- bool TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetNextColor(
- std::u16string::const_iterator start,
- std::u16string::const_iterator end,
- std::u16string& color) {
- std::u16string::const_iterator next_token;
- return GetNextColor(start, end, color, next_token);
- }
- absl::optional<SkColor> TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetNextColor(
- std::u16string::const_iterator start,
- std::u16string::const_iterator end,
- std::u16string::const_iterator& next_token) {
- std::u16string color;
- if (GetNextColor(start, end, color, next_token)) {
- if (base::StartsWith(color, u"hsl", base::CompareCase::SENSITIVE))
- return ParseHslString(color);
- if (base::StartsWith(color, u"rgb", base::CompareCase::SENSITIVE))
- return ParseRgbString(color);
- if (base::StartsWith(color, u"0x", base::CompareCase::INSENSITIVE_ASCII))
- return ParseHexString(color);
- SkColor value;
- if (base::StringToUint(color, &value))
- return absl::make_optional(value);
- }
- return absl::nullopt;
- }
- absl::optional<SkColor> TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::GetNextColor(
- std::u16string::const_iterator start,
- std::u16string::const_iterator end) {
- std::u16string::const_iterator next_token;
- return GetNextColor(start, end, next_token);
- }
- absl::optional<SkColor>
- TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::RgbaPiecesToSkColor(
- const std::vector<base::StringPiece16>& pieces,
- size_t start_piece) {
- int r, g, b;
- double a;
- return ((pieces.size() >= start_piece + 4) &&
- base::StringToInt(pieces[start_piece], &r) &&
- base::IsValueInRangeForNumericType<uint8_t>(r) &&
- base::StringToInt(pieces[start_piece + 1], &g) &&
- base::IsValueInRangeForNumericType<uint8_t>(g) &&
- base::StringToInt(pieces[start_piece + 2], &b) &&
- base::IsValueInRangeForNumericType<uint8_t>(b) &&
- base::StringToDouble(pieces[start_piece + 3], &a) && a >= 0.0 &&
- a <= 1.0)
- ? absl::make_optional(SkColorSetARGB(
- base::ClampRound<SkAlpha>(a * SK_AlphaOPAQUE), r, g, b))
- : absl::nullopt;
- }
- absl::optional<SkColor>
- TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::ParseHexString(
- const std::u16string& hex_string) {
- SkColor value;
- if (base::HexStringToUInt(base::UTF16ToUTF8(hex_string), &value)) {
- // Add in a 1.0 alpha channel if it wasn't included in the input.
- if (hex_string.length() <= 8)
- value = SkColorSetA(value, 0xFF);
- return absl::make_optional(value);
- }
- return absl::nullopt;
- }
- absl::optional<SkColor>
- TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::ParseHslString(
- const std::u16string& hsl_string) {
- std::u16string pruned_string;
- base::RemoveChars(hsl_string, u"(%)hsla", &pruned_string);
- const auto values = base::SplitStringPiece(
- pruned_string, u", ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- double h, s, v;
- double a = 1.0;
- if (values.size() >= 3 && values.size() <= 4 &&
- base::StringToDouble(values[0], &h) &&
- base::StringToDouble(values[1], &s) &&
- base::StringToDouble(values[2], &v) &&
- (values.size() == 3 ||
- (base::StringToDouble(values[3], &a) && a >= 0.0 && a <= 1.0))) {
- SkScalar hsv[3];
- hsv[0] = base::clamp(std::fmod(h, 360.0), 0.0, 360.0);
- hsv[1] =
- s > 1.0 ? base::clamp(s, 0.0, 100.0) / 100.0 : base::clamp(s, 0.0, 1.0);
- hsv[2] =
- v > 1.0 ? base::clamp(v, 0.0, 100.0) / 100.0 : base::clamp(v, 0.0, 1.0);
- return absl::make_optional(
- SkHSVToColor(base::ClampRound<SkAlpha>(a * SK_AlphaOPAQUE), hsv));
- }
- return absl::nullopt;
- }
- absl::optional<SkColor>
- TypeConverter<UNIQUE_TYPE_NAME(SkColor)>::ParseRgbString(
- const std::u16string& rgb_string) {
- // Declare a constant string here for use below since it might trigger an
- // ASAN error due to the stack temp going out of scope before the call to
- // RgbaPiecesToSkColor.
- std::u16string pruned_string;
- base::RemoveChars(rgb_string, u"()rgba", &pruned_string);
- auto values = base::SplitStringPiece(
- pruned_string, u", ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- // if it was just an rgb string, add the 1.0 alpha
- if (values.size() == 3)
- values.push_back(u"1.0");
- return RgbaPiecesToSkColor(values, 0);
- }
- } // namespace metadata
- } // namespace ui
- DEFINE_ENUM_CONVERTERS(gfx::HorizontalAlignment,
- {gfx::HorizontalAlignment::ALIGN_LEFT, u"ALIGN_LEFT"},
- {gfx::HorizontalAlignment::ALIGN_CENTER,
- u"ALIGN_CENTER"},
- {gfx::HorizontalAlignment::ALIGN_RIGHT, u"ALIGN_RIGHT"},
- {gfx::HorizontalAlignment::ALIGN_TO_HEAD,
- u"ALIGN_TO_HEAD"})
- DEFINE_ENUM_CONVERTERS(gfx::VerticalAlignment,
- {gfx::VerticalAlignment::ALIGN_TOP, u"ALIGN_TOP"},
- {gfx::VerticalAlignment::ALIGN_MIDDLE, u"ALIGN_MIDDLE"},
- {gfx::VerticalAlignment::ALIGN_BOTTOM, u"ALIGN_BOTTOM"})
- DEFINE_ENUM_CONVERTERS(gfx::ElideBehavior,
- {gfx::ElideBehavior::NO_ELIDE, u"NO_ELIDE"},
- {gfx::ElideBehavior::TRUNCATE, u"TRUNCATE"},
- {gfx::ElideBehavior::ELIDE_HEAD, u"ELIDE_HEAD"},
- {gfx::ElideBehavior::ELIDE_MIDDLE, u"ELIDE_MIDDLE"},
- {gfx::ElideBehavior::ELIDE_TAIL, u"ELIDE_TAIL"},
- {gfx::ElideBehavior::ELIDE_EMAIL, u"ELIDE_EMAIL"},
- {gfx::ElideBehavior::FADE_TAIL, u"FADE_TAIL"})
- DEFINE_ENUM_CONVERTERS(
- ui::MenuSeparatorType,
- {ui::MenuSeparatorType::NORMAL_SEPARATOR, u"NORMAL_SEPARATOR"},
- {ui::MenuSeparatorType::DOUBLE_SEPARATOR, u"DOUBLE_SEPARATOR"},
- {ui::MenuSeparatorType::UPPER_SEPARATOR, u"UPPER_SEPARATOR"},
- {ui::MenuSeparatorType::LOWER_SEPARATOR, u"LOWER_SEPARATOR"},
- {ui::MenuSeparatorType::SPACING_SEPARATOR, u"SPACING_SEPARATOR"},
- {ui::MenuSeparatorType::VERTICAL_SEPARATOR, u"VERTICAL_SEPARATOR"},
- {ui::MenuSeparatorType::PADDED_SEPARATOR, u"PADDED_SEPARATOR"})
|