Position.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /*
  2. * Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "Position.h"
  7. #include <LibGfx/Point.h>
  8. #include <LibGfx/Rect.h>
  9. namespace Web::CSS {
  10. CSSPixelPoint PositionValue::resolved(Layout::Node const& node, CSSPixelRect const& rect) const
  11. {
  12. // Note: A preset + a none default x/y_relative_to is impossible in the syntax (and makes little sense)
  13. CSSPixels x = horizontal_position.visit(
  14. [&](HorizontalPreset preset) -> CSSPixels {
  15. switch (preset) {
  16. case HorizontalPreset::Left:
  17. return 0;
  18. case HorizontalPreset::Center:
  19. return rect.width() / 2;
  20. case HorizontalPreset::Right:
  21. return rect.width();
  22. default:
  23. VERIFY_NOT_REACHED();
  24. }
  25. },
  26. [&](LengthPercentage length_percentage) -> CSSPixels {
  27. return length_percentage.to_px(node, rect.width());
  28. });
  29. CSSPixels y = vertical_position.visit(
  30. [&](VerticalPreset preset) -> CSSPixels {
  31. switch (preset) {
  32. case VerticalPreset::Top:
  33. return 0;
  34. case VerticalPreset::Center:
  35. return rect.height() / 2;
  36. case VerticalPreset::Bottom:
  37. return rect.height();
  38. default:
  39. VERIFY_NOT_REACHED();
  40. }
  41. },
  42. [&](LengthPercentage length_percentage) -> CSSPixels {
  43. return length_percentage.to_px(node, rect.height());
  44. });
  45. if (x_relative_to == HorizontalEdge::Right)
  46. x = rect.width() - x;
  47. if (y_relative_to == VerticalEdge::Bottom)
  48. y = rect.height() - y;
  49. return CSSPixelPoint { rect.x() + x, rect.y() + y };
  50. }
  51. void PositionValue::serialize(StringBuilder& builder) const
  52. {
  53. // Note: This means our serialization with simplify any with explicit edges that are just `top left`.
  54. bool has_relative_edges = x_relative_to == HorizontalEdge::Right || y_relative_to == VerticalEdge::Bottom;
  55. if (has_relative_edges)
  56. builder.append(x_relative_to == HorizontalEdge::Left ? "left "sv : "right "sv);
  57. horizontal_position.visit(
  58. [&](HorizontalPreset preset) {
  59. builder.append([&] {
  60. switch (preset) {
  61. case HorizontalPreset::Left:
  62. return "left"sv;
  63. case HorizontalPreset::Center:
  64. return "center"sv;
  65. case HorizontalPreset::Right:
  66. return "right"sv;
  67. default:
  68. VERIFY_NOT_REACHED();
  69. }
  70. }());
  71. },
  72. [&](LengthPercentage length_percentage) {
  73. builder.append(length_percentage.to_string());
  74. });
  75. builder.append(' ');
  76. if (has_relative_edges)
  77. builder.append(y_relative_to == VerticalEdge::Top ? "top "sv : "bottom "sv);
  78. vertical_position.visit(
  79. [&](VerticalPreset preset) {
  80. builder.append([&] {
  81. switch (preset) {
  82. case VerticalPreset::Top:
  83. return "top"sv;
  84. case VerticalPreset::Center:
  85. return "center"sv;
  86. case VerticalPreset::Bottom:
  87. return "bottom"sv;
  88. default:
  89. VERIFY_NOT_REACHED();
  90. }
  91. }());
  92. },
  93. [&](LengthPercentage length_percentage) {
  94. builder.append(length_percentage.to_string());
  95. });
  96. }
  97. }