2020-10-05 16:14:36 -07:00
/*
2021-04-22 16:53:07 -07:00
* Copyright ( c ) 2020 , Matthew Olsson < mattco @ serenityos . org >
2022-07-11 12:25:01 +02:00
* Copyright ( c ) 2022 , Andreas Kling < kling @ serenityos . org >
2020-10-05 16:14:36 -07:00
*
2021-04-22 01:24:48 -07:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-10-05 16:14:36 -07:00
*/
2023-03-19 15:44:12 +01:00
# include <LibWeb/CSS/Parser/Parser.h>
2022-03-18 22:13:26 +01:00
# include <LibWeb/Layout/ReplacedBox.h>
2022-07-11 12:25:01 +02:00
# include <LibWeb/Layout/SVGGeometryBox.h>
2022-03-10 22:38:08 +01:00
# include <LibWeb/Painting/SVGSVGPaintable.h>
2020-10-05 16:14:36 -07:00
2020-11-22 15:53:01 +01:00
namespace Web : : Layout {
2020-10-05 16:14:36 -07:00
2024-04-06 10:16:04 -07:00
JS_DEFINE_ALLOCATOR ( SVGSVGBox ) ;
2020-11-22 15:53:01 +01:00
SVGSVGBox : : SVGSVGBox ( DOM : : Document & document , SVG : : SVGSVGElement & element , NonnullRefPtr < CSS : : StyleProperties > properties )
2022-03-18 22:13:26 +01:00
: ReplacedBox ( document , element , move ( properties ) )
2020-10-05 16:14:36 -07:00
{
}
2023-01-11 12:51:49 +01:00
JS : : GCPtr < Painting : : Paintable > SVGSVGBox : : create_paintable ( ) const
2022-03-10 22:38:08 +01:00
{
return Painting : : SVGSVGPaintable : : create ( * this ) ;
}
2022-07-11 12:25:01 +02:00
void SVGSVGBox : : prepare_for_replaced_layout ( )
{
2023-05-19 18:14:37 +02:00
// https://www.w3.org/TR/SVG2/coords.html#SizingSVGInCSS
// The intrinsic dimensions must also be determined from the width and height sizing properties.
// If either width or height are not specified, the used value is the initial value 'auto'.
// 'auto' and percentage lengths must not be used to determine an intrinsic width or intrinsic height.
auto const & computed_width = computed_values ( ) . width ( ) ;
if ( computed_width . is_length ( ) & & ! computed_width . contains_percentage ( ) ) {
2023-06-08 15:56:28 +01:00
set_natural_width ( computed_width . to_px ( * this , 0 ) ) ;
2022-07-11 12:25:01 +02:00
}
2023-05-19 18:14:37 +02:00
auto const & computed_height = computed_values ( ) . height ( ) ;
if ( computed_height . is_length ( ) & & ! computed_height . contains_percentage ( ) ) {
2023-06-08 15:56:28 +01:00
set_natural_height ( computed_height . to_px ( * this , 0 ) ) ;
2023-05-19 18:14:37 +02:00
}
2023-06-08 15:56:28 +01:00
set_natural_aspect_ratio ( calculate_intrinsic_aspect_ratio ( ) ) ;
2023-05-19 18:14:37 +02:00
}
2022-07-11 12:25:01 +02:00
2023-09-03 17:33:58 -05:00
Optional < CSSPixelFraction > SVGSVGBox : : calculate_intrinsic_aspect_ratio ( ) const
2023-05-19 18:14:37 +02:00
{
// https://www.w3.org/TR/SVG2/coords.html#SizingSVGInCSS
// The intrinsic aspect ratio must be calculated using the following algorithm. If the algorithm returns null, then there is no intrinsic aspect ratio.
2022-07-11 12:25:01 +02:00
2023-05-19 18:14:37 +02:00
auto const & computed_width = computed_values ( ) . width ( ) ;
auto const & computed_height = computed_values ( ) . height ( ) ;
2022-07-11 12:25:01 +02:00
2023-05-19 18:14:37 +02:00
// 1. If the width and height sizing properties on the ‘ svg’ element are both absolute values:
if ( computed_width . is_length ( ) & & ! computed_width . contains_percentage ( ) & & computed_height . is_length ( ) & & ! computed_height . contains_percentage ( ) ) {
auto width = computed_width . to_px ( * this , 0 ) ;
auto height = computed_height . to_px ( * this , 0 ) ;
2022-07-11 12:25:01 +02:00
2023-05-19 18:14:37 +02:00
if ( width ! = 0 & & height ! = 0 ) {
// 1. return width / height
2023-09-03 17:33:58 -05:00
return width / height ;
2022-07-11 12:25:01 +02:00
}
2023-05-19 18:14:37 +02:00
return { } ;
}
// FIXME: 2. If an SVG View is active:
// FIXME: 1. let viewbox be the viewbox defined by the active SVG View
// FIXME: 2. return viewbox.width / viewbox.height
2022-07-11 12:25:01 +02:00
2023-05-19 18:14:37 +02:00
// 3. If the ‘ viewBox’ on the ‘ svg’ element is correctly specified:
if ( dom_node ( ) . view_box ( ) . has_value ( ) ) {
// 1. let viewbox be the viewbox defined by the ‘ viewBox’ attribute on the ‘ svg’ element
auto const & viewbox = dom_node ( ) . view_box ( ) . value ( ) ;
// 2. return viewbox.width / viewbox.height
2024-07-21 21:58:24 +01:00
auto viewbox_width = CSSPixels : : nearest_value_for ( viewbox . width ) ;
2024-03-19 23:45:34 +00:00
auto viewbox_height = CSSPixels : : nearest_value_for ( viewbox . height ) ;
2024-07-21 21:58:24 +01:00
if ( viewbox_width ! = 0 & & viewbox_height ! = 0 )
return viewbox_width / viewbox_height ;
2024-03-17 08:37:45 +00:00
return { } ;
2022-07-11 12:25:01 +02:00
}
2023-05-19 18:14:37 +02:00
// 4. return null
return { } ;
2022-07-11 12:25:01 +02:00
}
2020-10-05 16:14:36 -07:00
}