SVGSVGBox.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /*
  2. * Copyright (c) 2020, Matthew Olsson <mattco@serenityos.org>
  3. * Copyright (c) 2022-2024, Andreas Kling <andreas@ladybird.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <LibWeb/CSS/Parser/Parser.h>
  8. #include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
  9. #include <LibWeb/Layout/ReplacedBox.h>
  10. #include <LibWeb/Layout/SVGGeometryBox.h>
  11. #include <LibWeb/Painting/SVGSVGPaintable.h>
  12. namespace Web::Layout {
  13. JS_DEFINE_ALLOCATOR(SVGSVGBox);
  14. SVGSVGBox::SVGSVGBox(DOM::Document& document, SVG::SVGSVGElement& element, NonnullRefPtr<CSS::StyleProperties> properties)
  15. : ReplacedBox(document, element, move(properties))
  16. {
  17. }
  18. JS::GCPtr<Painting::Paintable> SVGSVGBox::create_paintable() const
  19. {
  20. return Painting::SVGSVGPaintable::create(*this);
  21. }
  22. void SVGSVGBox::prepare_for_replaced_layout()
  23. {
  24. // https://www.w3.org/TR/SVG2/coords.html#SizingSVGInCSS
  25. // The intrinsic dimensions must also be determined from the width and height sizing properties.
  26. // If either width or height are not specified, the used value is the initial value 'auto'.
  27. // 'auto' and percentage lengths must not be used to determine an intrinsic width or intrinsic height.
  28. Optional<CSSPixels> natural_width;
  29. if (auto width = dom_node().width_style_value_from_attribute(); width && width->is_length() && width->as_length().length().is_absolute()) {
  30. natural_width = width->as_length().length().absolute_length_to_px();
  31. }
  32. Optional<CSSPixels> natural_height;
  33. if (auto height = dom_node().height_style_value_from_attribute(); height && height->is_length() && height->as_length().length().is_absolute()) {
  34. natural_height = height->as_length().length().absolute_length_to_px();
  35. }
  36. // The intrinsic aspect ratio must be calculated using the following algorithm. If the algorithm returns null, then there is no intrinsic aspect ratio.
  37. auto natural_aspect_ratio = [&]() -> Optional<CSSPixelFraction> {
  38. // 1. If the width and height sizing properties on the ‘svg’ element are both absolute values:
  39. if (natural_width.has_value() && natural_height.has_value()) {
  40. if (natural_width != 0 && natural_height != 0) {
  41. // 1. return width / height
  42. return *natural_width / *natural_height;
  43. }
  44. return {};
  45. }
  46. // FIXME: 2. If an SVG View is active:
  47. // FIXME: 1. let viewbox be the viewbox defined by the active SVG View
  48. // FIXME: 2. return viewbox.width / viewbox.height
  49. // 3. If the ‘viewBox’ on the ‘svg’ element is correctly specified:
  50. if (dom_node().view_box().has_value()) {
  51. // 1. let viewbox be the viewbox defined by the ‘viewBox’ attribute on the ‘svg’ element
  52. auto const& viewbox = dom_node().view_box().value();
  53. // 2. return viewbox.width / viewbox.height
  54. auto viewbox_width = CSSPixels::nearest_value_for(viewbox.width);
  55. auto viewbox_height = CSSPixels::nearest_value_for(viewbox.height);
  56. if (viewbox_width != 0 && viewbox_height != 0)
  57. return viewbox_width / viewbox_height;
  58. return {};
  59. }
  60. // 4. return null
  61. return {};
  62. }();
  63. set_natural_width(natural_width);
  64. set_natural_height(natural_height);
  65. set_natural_aspect_ratio(natural_aspect_ratio);
  66. }
  67. }