ShorthandStyleValue.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * Copyright (c) 2023, Ali Mohammad Pur <mpfard@serenityos.org>
  3. * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include "ShorthandStyleValue.h"
  8. #include <LibWeb/CSS/PropertyID.h>
  9. #include <LibWeb/CSS/StyleValues/BorderRadiusStyleValue.h>
  10. #include <LibWeb/CSS/StyleValues/StyleValueList.h>
  11. namespace Web::CSS {
  12. ShorthandStyleValue::ShorthandStyleValue(PropertyID shorthand, Vector<PropertyID> sub_properties, Vector<ValueComparingNonnullRefPtr<StyleValue const>> values)
  13. : StyleValueWithDefaultOperators(Type::Shorthand)
  14. , m_properties { shorthand, move(sub_properties), move(values) }
  15. {
  16. if (m_properties.sub_properties.size() != m_properties.values.size()) {
  17. dbgln("ShorthandStyleValue: sub_properties and values must be the same size! {} != {}", m_properties.sub_properties.size(), m_properties.values.size());
  18. VERIFY_NOT_REACHED();
  19. }
  20. }
  21. ShorthandStyleValue::~ShorthandStyleValue() = default;
  22. ValueComparingRefPtr<StyleValue const> ShorthandStyleValue::longhand(PropertyID longhand) const
  23. {
  24. for (auto i = 0u; i < m_properties.sub_properties.size(); ++i) {
  25. if (m_properties.sub_properties[i] == longhand)
  26. return m_properties.values[i];
  27. }
  28. return nullptr;
  29. }
  30. String ShorthandStyleValue::to_string() const
  31. {
  32. // Special-cases first
  33. switch (m_properties.shorthand_property) {
  34. case PropertyID::Background: {
  35. auto color = longhand(PropertyID::BackgroundColor);
  36. auto image = longhand(PropertyID::BackgroundImage);
  37. auto position = longhand(PropertyID::BackgroundPosition);
  38. auto size = longhand(PropertyID::BackgroundSize);
  39. auto repeat = longhand(PropertyID::BackgroundRepeat);
  40. auto attachment = longhand(PropertyID::BackgroundAttachment);
  41. auto origin = longhand(PropertyID::BackgroundOrigin);
  42. auto clip = longhand(PropertyID::BackgroundClip);
  43. auto get_layer_count = [](auto style_value) -> size_t {
  44. return style_value->is_value_list() ? style_value->as_value_list().size() : 1;
  45. };
  46. auto layer_count = max(get_layer_count(image), max(get_layer_count(position), max(get_layer_count(size), max(get_layer_count(repeat), max(get_layer_count(attachment), max(get_layer_count(origin), get_layer_count(clip)))))));
  47. if (layer_count == 1) {
  48. return MUST(String::formatted("{} {} {} {} {} {} {} {}", color->to_string(), image->to_string(), position->to_string(), size->to_string(), repeat->to_string(), attachment->to_string(), origin->to_string(), clip->to_string()));
  49. }
  50. auto get_layer_value_string = [](ValueComparingRefPtr<StyleValue const> const& style_value, size_t index) {
  51. if (style_value->is_value_list())
  52. return style_value->as_value_list().value_at(index, true)->to_string();
  53. return style_value->to_string();
  54. };
  55. StringBuilder builder;
  56. for (size_t i = 0; i < layer_count; i++) {
  57. if (i)
  58. builder.append(", "sv);
  59. if (i == layer_count - 1)
  60. builder.appendff("{} ", color->to_string());
  61. builder.appendff("{} {} {} {} {} {} {}", get_layer_value_string(image, i), get_layer_value_string(position, i), get_layer_value_string(size, i), get_layer_value_string(repeat, i), get_layer_value_string(attachment, i), get_layer_value_string(origin, i), get_layer_value_string(clip, i));
  62. }
  63. return MUST(builder.to_string());
  64. }
  65. case PropertyID::BorderRadius: {
  66. auto& top_left = longhand(PropertyID::BorderTopLeftRadius)->as_border_radius();
  67. auto& top_right = longhand(PropertyID::BorderTopRightRadius)->as_border_radius();
  68. auto& bottom_right = longhand(PropertyID::BorderBottomRightRadius)->as_border_radius();
  69. auto& bottom_left = longhand(PropertyID::BorderBottomLeftRadius)->as_border_radius();
  70. return MUST(String::formatted("{} {} {} {} / {} {} {} {}",
  71. top_left.horizontal_radius().to_string(),
  72. top_right.horizontal_radius().to_string(),
  73. bottom_right.horizontal_radius().to_string(),
  74. bottom_left.horizontal_radius().to_string(),
  75. top_left.vertical_radius().to_string(),
  76. top_right.vertical_radius().to_string(),
  77. bottom_right.vertical_radius().to_string(),
  78. bottom_left.vertical_radius().to_string()));
  79. }
  80. case PropertyID::Flex:
  81. return MUST(String::formatted("{} {} {}", longhand(PropertyID::FlexGrow)->to_string(), longhand(PropertyID::FlexShrink)->to_string(), longhand(PropertyID::FlexBasis)->to_string()));
  82. case PropertyID::FlexFlow:
  83. return MUST(String::formatted("{} {}", longhand(PropertyID::FlexDirection)->to_string(), longhand(PropertyID::FlexWrap)->to_string()));
  84. default:
  85. StringBuilder builder;
  86. auto first = true;
  87. for (auto& value : m_properties.values) {
  88. if (first)
  89. first = false;
  90. else
  91. builder.append(' ');
  92. builder.append(value->to_string());
  93. }
  94. return MUST(builder.to_string());
  95. }
  96. }
  97. }