LinearGradientStyleValue.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
  4. * Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
  5. * Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
  6. *
  7. * SPDX-License-Identifier: BSD-2-Clause
  8. */
  9. #include "LinearGradientStyleValue.h"
  10. namespace Web::CSS {
  11. ErrorOr<String> LinearGradientStyleValue::to_string() const
  12. {
  13. StringBuilder builder;
  14. auto side_or_corner_to_string = [](SideOrCorner value) {
  15. switch (value) {
  16. case SideOrCorner::Top:
  17. return "top"sv;
  18. case SideOrCorner::Bottom:
  19. return "bottom"sv;
  20. case SideOrCorner::Left:
  21. return "left"sv;
  22. case SideOrCorner::Right:
  23. return "right"sv;
  24. case SideOrCorner::TopLeft:
  25. return "top left"sv;
  26. case SideOrCorner::TopRight:
  27. return "top right"sv;
  28. case SideOrCorner::BottomLeft:
  29. return "bottom left"sv;
  30. case SideOrCorner::BottomRight:
  31. return "bottom right"sv;
  32. default:
  33. VERIFY_NOT_REACHED();
  34. }
  35. };
  36. if (m_properties.gradient_type == GradientType::WebKit)
  37. TRY(builder.try_append("-webkit-"sv));
  38. if (is_repeating())
  39. TRY(builder.try_append("repeating-"sv));
  40. TRY(builder.try_append("linear-gradient("sv));
  41. TRY(m_properties.direction.visit(
  42. [&](SideOrCorner side_or_corner) -> ErrorOr<void> {
  43. return builder.try_appendff("{}{}, "sv, m_properties.gradient_type == GradientType::Standard ? "to "sv : ""sv, side_or_corner_to_string(side_or_corner));
  44. },
  45. [&](Angle const& angle) -> ErrorOr<void> {
  46. return builder.try_appendff("{}, "sv, TRY(angle.to_string()));
  47. }));
  48. TRY(serialize_color_stop_list(builder, m_properties.color_stop_list));
  49. TRY(builder.try_append(")"sv));
  50. return builder.to_string();
  51. }
  52. bool LinearGradientStyleValue::equals(StyleValue const& other_) const
  53. {
  54. if (type() != other_.type())
  55. return false;
  56. auto& other = other_.as_linear_gradient();
  57. return m_properties == other.m_properties;
  58. }
  59. float LinearGradientStyleValue::angle_degrees(CSSPixelSize gradient_size) const
  60. {
  61. auto corner_angle_degrees = [&] {
  62. return static_cast<float>(atan2(gradient_size.height().value(), gradient_size.width().value())) * 180 / AK::Pi<float>;
  63. };
  64. return m_properties.direction.visit(
  65. [&](SideOrCorner side_or_corner) {
  66. auto angle = [&] {
  67. switch (side_or_corner) {
  68. case SideOrCorner::Top:
  69. return 0.0f;
  70. case SideOrCorner::Bottom:
  71. return 180.0f;
  72. case SideOrCorner::Left:
  73. return 270.0f;
  74. case SideOrCorner::Right:
  75. return 90.0f;
  76. case SideOrCorner::TopRight:
  77. return corner_angle_degrees();
  78. case SideOrCorner::BottomLeft:
  79. return corner_angle_degrees() + 180.0f;
  80. case SideOrCorner::TopLeft:
  81. return -corner_angle_degrees();
  82. case SideOrCorner::BottomRight:
  83. return -(corner_angle_degrees() + 180.0f);
  84. default:
  85. VERIFY_NOT_REACHED();
  86. }
  87. }();
  88. // Note: For unknowable reasons the angles are opposite on the -webkit- version
  89. if (m_properties.gradient_type == GradientType::WebKit)
  90. return angle + 180.0f;
  91. return angle;
  92. },
  93. [&](Angle const& angle) {
  94. return angle.to_degrees();
  95. });
  96. }
  97. void LinearGradientStyleValue::resolve_for_size(Layout::Node const& node, CSSPixelSize size) const
  98. {
  99. if (m_resolved.has_value() && m_resolved->size == size)
  100. return;
  101. m_resolved = ResolvedData { Painting::resolve_linear_gradient_data(node, size, *this), size };
  102. }
  103. void LinearGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering) const
  104. {
  105. VERIFY(m_resolved.has_value());
  106. Painting::paint_linear_gradient(context, dest_rect, m_resolved->data);
  107. }
  108. }