diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/CSS/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibWeb/CSS/BUILD.gn index b46d00d4d9e..780c425244d 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/CSS/BUILD.gn +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/CSS/BUILD.gn @@ -60,6 +60,7 @@ source_set("CSS") { "SelectorEngine.cpp", "Serialize.cpp", "Size.cpp", + "Sizing.cpp", "StyleComputer.cpp", "StyleInvalidation.cpp", "StyleProperties.cpp", diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index c38d2f065e5..883138bba27 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -99,6 +99,7 @@ set(SOURCES CSS/SelectorEngine.cpp CSS/Serialize.cpp CSS/Size.cpp + CSS/Sizing.cpp CSS/StyleComputer.cpp CSS/StyleInvalidation.cpp CSS/StyleProperties.cpp diff --git a/Userland/Libraries/LibWeb/CSS/Sizing.cpp b/Userland/Libraries/LibWeb/CSS/Sizing.cpp new file mode 100644 index 00000000000..74d58c7c8a9 --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/Sizing.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022, MacDue + * Copyright (c) 2024, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "Sizing.h" + +namespace Web::CSS { + +// https://drafts.csswg.org/css-images/#default-sizing +CSSPixelSize run_default_sizing_algorithm( + Optional specified_width, Optional specified_height, + Optional natural_width, Optional natural_height, + Optional natural_aspect_ratio, + CSSPixelSize default_size) +{ + // If the specified size is a definite width and height, the concrete object size is given that width and height. + if (specified_width.has_value() && specified_height.has_value()) + return CSSPixelSize { specified_width.value(), specified_height.value() }; + // If the specified size is only a width or height (but not both) then the concrete object size is given that specified width or height. + // The other dimension is calculated as follows: + if (specified_width.has_value() || specified_height.has_value()) { + // 1. If the object has a natural aspect ratio, + // the missing dimension of the concrete object size is calculated using that aspect ratio and the present dimension. + if (natural_aspect_ratio.has_value() && !natural_aspect_ratio->might_be_saturated()) { + if (specified_width.has_value()) + return CSSPixelSize { specified_width.value(), (CSSPixels(1) / natural_aspect_ratio.value()) * specified_width.value() }; + if (specified_height.has_value()) + return CSSPixelSize { specified_height.value() * natural_aspect_ratio.value(), specified_height.value() }; + } + // 2. Otherwise, if the missing dimension is present in the object’s natural dimensions, + // the missing dimension is taken from the object’s natural dimensions. + if (specified_height.has_value() && natural_width.has_value()) + return CSSPixelSize { natural_width.value(), specified_height.value() }; + if (specified_width.has_value() && natural_height.has_value()) + return CSSPixelSize { specified_width.value(), natural_height.value() }; + // 3. Otherwise, the missing dimension of the concrete object size is taken from the default object size. + if (specified_height.has_value()) + return CSSPixelSize { default_size.width(), specified_height.value() }; + if (specified_width.has_value()) + return CSSPixelSize { specified_width.value(), default_size.height() }; + VERIFY_NOT_REACHED(); + } + // If the specified size has no constraints: + // 1. If the object has a natural height or width, its size is resolved as if its natural dimensions were given as the specified size. + if (natural_width.has_value() || natural_height.has_value()) + return run_default_sizing_algorithm(natural_width, natural_height, natural_width, natural_height, natural_aspect_ratio, default_size); + // FIXME: 2. Otherwise, its size is resolved as a contain constraint against the default object size. + return default_size; +} + +} diff --git a/Userland/Libraries/LibWeb/CSS/Sizing.h b/Userland/Libraries/LibWeb/CSS/Sizing.h new file mode 100644 index 00000000000..f1cc8e006b3 --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/Sizing.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Web::CSS { + +// https://drafts.csswg.org/css-images/#default-sizing +CSSPixelSize run_default_sizing_algorithm( + Optional specified_width, Optional specified_height, + Optional natural_width, Optional natural_height, + Optional natural_aspect_ratio, + CSSPixelSize default_size); + +} diff --git a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp index 920f23cc6f9..324339c537b 100644 --- a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp @@ -6,6 +6,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -14,48 +15,6 @@ namespace Web::Painting { -// https://drafts.csswg.org/css-images/#default-sizing -static CSSPixelSize run_default_sizing_algorithm( - Optional specified_width, Optional specified_height, - Optional natural_width, Optional natural_height, - Optional natural_aspect_ratio, - CSSPixelSize default_size) -{ - // If the specified size is a definite width and height, the concrete object size is given that width and height. - if (specified_width.has_value() && specified_height.has_value()) - return CSSPixelSize { specified_width.value(), specified_height.value() }; - // If the specified size is only a width or height (but not both) then the concrete object size is given that specified width or height. - // The other dimension is calculated as follows: - if (specified_width.has_value() || specified_height.has_value()) { - // 1. If the object has a natural aspect ratio, - // the missing dimension of the concrete object size is calculated using that aspect ratio and the present dimension. - if (natural_aspect_ratio.has_value() && !natural_aspect_ratio->might_be_saturated()) { - if (specified_width.has_value()) - return CSSPixelSize { specified_width.value(), (CSSPixels(1) / natural_aspect_ratio.value()) * specified_width.value() }; - if (specified_height.has_value()) - return CSSPixelSize { specified_height.value() * natural_aspect_ratio.value(), specified_height.value() }; - } - // 2. Otherwise, if the missing dimension is present in the object’s natural dimensions, - // the missing dimension is taken from the object’s natural dimensions. - if (specified_height.has_value() && natural_width.has_value()) - return CSSPixelSize { natural_width.value(), specified_height.value() }; - if (specified_width.has_value() && natural_height.has_value()) - return CSSPixelSize { specified_width.value(), natural_height.value() }; - // 3. Otherwise, the missing dimension of the concrete object size is taken from the default object size. - if (specified_height.has_value()) - return CSSPixelSize { default_size.width(), specified_height.value() }; - if (specified_width.has_value()) - return CSSPixelSize { specified_width.value(), default_size.height() }; - VERIFY_NOT_REACHED(); - } - // If the specified size has no constraints: - // 1. If the object has a natural height or width, its size is resolved as if its natural dimensions were given as the specified size. - if (natural_width.has_value() || natural_height.has_value()) - return run_default_sizing_algorithm(natural_width, natural_height, natural_width, natural_height, natural_aspect_ratio, default_size); - // FIXME: 2. Otherwise, its size is resolved as a contain constraint against the default object size. - return default_size; -} - static RefPtr compute_text_clip_paths(PaintContext& context, Paintable const& paintable, CSSPixelPoint containing_block_location) { auto text_clip_paths = DisplayList::create(); @@ -373,7 +332,7 @@ ResolvedBackground resolve_background_layers(Vector co if (!layer.size_y.is_auto()) specified_height = layer.size_y.to_px(layout_node, background_positioning_area.height()); } - auto concrete_image_size = run_default_sizing_algorithm( + auto concrete_image_size = CSS::run_default_sizing_algorithm( specified_width, specified_height, image.natural_width(), image.natural_height(), image.natural_aspect_ratio(), background_positioning_area.size());