2020-01-18 05:38:21 -03:00
|
|
|
/*
|
2024-08-02 09:28:24 -03:00
|
|
|
* Copyright (c) 2018-2024, Andreas Kling <andreas@ladybird.org>
|
2025-05-16 16:02:16 -03:00
|
|
|
* Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org>
|
2020-01-18 05:38:21 -03:00
|
|
|
*
|
2021-04-22 05:24:48 -03:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-01-18 05:38:21 -03:00
|
|
|
*/
|
|
|
|
|
|
2019-07-01 12:17:32 -03:00
|
|
|
#pragma once
|
|
|
|
|
|
2023-01-06 15:02:26 -03:00
|
|
|
#include <AK/String.h>
|
2021-09-23 08:13:51 -03:00
|
|
|
#include <LibGfx/Forward.h>
|
2023-06-02 07:39:39 -03:00
|
|
|
#include <LibGfx/Rect.h>
|
2025-05-16 16:02:16 -03:00
|
|
|
#include <LibWeb/CSS/SerializationMode.h>
|
2025-09-02 09:48:49 -03:00
|
|
|
#include <LibWeb/CSS/Units.h>
|
2025-07-19 23:35:33 -03:00
|
|
|
#include <LibWeb/Export.h>
|
2020-06-07 12:55:46 -03:00
|
|
|
#include <LibWeb/Forward.h>
|
2022-10-24 13:16:08 -03:00
|
|
|
#include <LibWeb/PixelUnits.h>
|
2019-07-03 02:55:22 -03:00
|
|
|
|
2020-07-26 15:01:35 -03:00
|
|
|
namespace Web::CSS {
|
2020-03-07 06:27:02 -03:00
|
|
|
|
2025-07-19 23:35:33 -03:00
|
|
|
class WEB_API Length {
|
2019-07-01 12:17:32 -03:00
|
|
|
public:
|
2023-04-28 12:29:12 -03:00
|
|
|
struct FontMetrics {
|
2024-01-12 08:39:40 -03:00
|
|
|
FontMetrics(CSSPixels font_size, Gfx::FontPixelMetrics const&);
|
2023-04-28 12:29:12 -03:00
|
|
|
|
|
|
|
|
CSSPixels font_size;
|
|
|
|
|
CSSPixels x_height;
|
2023-04-28 13:10:30 -03:00
|
|
|
CSSPixels cap_height;
|
2023-04-28 12:29:12 -03:00
|
|
|
CSSPixels zero_advance;
|
|
|
|
|
CSSPixels line_height;
|
2025-02-21 13:45:07 -03:00
|
|
|
|
|
|
|
|
bool operator==(FontMetrics const&) const = default;
|
2023-04-28 12:29:12 -03:00
|
|
|
};
|
|
|
|
|
|
2025-09-02 09:48:49 -03:00
|
|
|
Length(double value, LengthUnit unit);
|
2022-09-13 12:42:39 -03:00
|
|
|
~Length();
|
2019-07-01 12:17:32 -03:00
|
|
|
|
2025-01-23 13:48:03 -03:00
|
|
|
static Length make_px(double value);
|
2022-10-24 13:16:08 -03:00
|
|
|
static Length make_px(CSSPixels value);
|
2022-01-14 09:23:54 -03:00
|
|
|
Length percentage_of(Percentage const&) const;
|
2020-06-24 06:08:46 -03:00
|
|
|
|
2025-09-02 09:48:49 -03:00
|
|
|
bool is_px() const { return m_unit == LengthUnit::Px; }
|
2023-04-26 13:37:57 -03:00
|
|
|
|
2025-09-02 09:48:49 -03:00
|
|
|
bool is_absolute() const { return CSS::is_absolute(m_unit); }
|
|
|
|
|
bool is_font_relative() const { return CSS::is_font_relative(m_unit); }
|
|
|
|
|
bool is_viewport_relative() const { return CSS::is_viewport_relative(m_unit); }
|
|
|
|
|
bool is_relative() const { return CSS::is_relative(m_unit); }
|
2023-04-26 13:37:57 -03:00
|
|
|
|
2023-05-24 05:50:57 -03:00
|
|
|
double raw_value() const { return m_value; }
|
2025-09-02 09:48:49 -03:00
|
|
|
LengthUnit unit() const { return m_unit; }
|
2025-09-11 07:50:59 -03:00
|
|
|
FlyString unit_name() const { return CSS::to_string(m_unit); }
|
2021-09-23 08:13:51 -03:00
|
|
|
|
2023-06-02 07:39:39 -03:00
|
|
|
struct ResolutionContext {
|
2025-07-19 00:38:16 -03:00
|
|
|
[[nodiscard]] static ResolutionContext for_element(DOM::AbstractElement const&);
|
2025-02-21 13:45:07 -03:00
|
|
|
[[nodiscard]] static ResolutionContext for_window(HTML::Window const&);
|
|
|
|
|
[[nodiscard]] static ResolutionContext for_layout_node(Layout::Node const&);
|
2023-06-02 07:39:39 -03:00
|
|
|
|
|
|
|
|
CSSPixelRect viewport_rect;
|
|
|
|
|
FontMetrics font_metrics;
|
|
|
|
|
FontMetrics root_font_metrics;
|
2025-02-21 13:45:07 -03:00
|
|
|
|
|
|
|
|
bool operator==(ResolutionContext const&) const = default;
|
2023-06-02 07:39:39 -03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] CSSPixels to_px(ResolutionContext const&) const;
|
|
|
|
|
|
2024-03-02 07:17:06 -03:00
|
|
|
[[nodiscard]] ALWAYS_INLINE CSSPixels to_px(Layout::Node const& node) const
|
|
|
|
|
{
|
|
|
|
|
if (is_absolute())
|
|
|
|
|
return absolute_length_to_px();
|
|
|
|
|
return to_px_slow_case(node);
|
|
|
|
|
}
|
2021-09-23 08:13:51 -03:00
|
|
|
|
2023-04-28 12:29:12 -03:00
|
|
|
ALWAYS_INLINE CSSPixels to_px(CSSPixelRect const& viewport_rect, FontMetrics const& font_metrics, FontMetrics const& root_font_metrics) const
|
2020-06-23 18:21:58 -03:00
|
|
|
{
|
2024-10-16 10:00:25 -03:00
|
|
|
if (is_absolute())
|
|
|
|
|
return absolute_length_to_px();
|
2023-04-28 16:07:41 -03:00
|
|
|
if (is_font_relative())
|
|
|
|
|
return font_relative_length_to_px(font_metrics, root_font_metrics);
|
|
|
|
|
if (is_viewport_relative())
|
|
|
|
|
return viewport_relative_length_to_px(viewport_rect);
|
2024-10-16 10:00:25 -03:00
|
|
|
|
|
|
|
|
VERIFY_NOT_REACHED();
|
2021-10-05 11:39:40 -03:00
|
|
|
}
|
|
|
|
|
|
2022-11-08 14:29:52 -03:00
|
|
|
ALWAYS_INLINE CSSPixels absolute_length_to_px() const
|
2025-07-31 06:07:03 -03:00
|
|
|
{
|
|
|
|
|
return CSSPixels::nearest_value_for(absolute_length_to_px_without_rounding());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ALWAYS_INLINE double absolute_length_to_px_without_rounding() const
|
2021-10-05 11:39:40 -03:00
|
|
|
{
|
2025-09-04 08:27:20 -03:00
|
|
|
return ratio_between_units(m_unit, LengthUnit::Px) * m_value;
|
2020-06-23 18:21:58 -03:00
|
|
|
}
|
2019-07-01 12:17:32 -03:00
|
|
|
|
2025-05-16 16:02:16 -03:00
|
|
|
String to_string(SerializationMode = SerializationMode::Normal) const;
|
2019-07-24 02:34:07 -03:00
|
|
|
|
2023-03-30 11:46:05 -03:00
|
|
|
bool operator==(Length const& other) const
|
|
|
|
|
{
|
2025-09-02 09:48:49 -03:00
|
|
|
return m_unit == other.m_unit && m_value == other.m_value;
|
2023-03-30 11:46:05 -03:00
|
|
|
}
|
2020-12-15 15:39:33 -03:00
|
|
|
|
2023-04-28 16:07:41 -03:00
|
|
|
CSSPixels font_relative_length_to_px(FontMetrics const& font_metrics, FontMetrics const& root_font_metrics) const;
|
|
|
|
|
CSSPixels viewport_relative_length_to_px(CSSPixelRect const& viewport_rect) const;
|
2021-09-23 08:13:51 -03:00
|
|
|
|
2023-03-30 11:01:23 -03:00
|
|
|
// Returns empty optional if it's already absolute.
|
2023-04-28 12:29:12 -03:00
|
|
|
Optional<Length> absolutize(CSSPixelRect const& viewport_rect, FontMetrics const& font_metrics, FontMetrics const& root_font_metrics) const;
|
|
|
|
|
Length absolutized(CSSPixelRect const& viewport_rect, FontMetrics const& font_metrics, FontMetrics const& root_font_metrics) const;
|
2023-03-30 11:01:23 -03:00
|
|
|
|
2025-04-15 18:18:27 -03:00
|
|
|
static Length resolve_calculated(NonnullRefPtr<CalculatedStyleValue const> const&, Layout::Node const&, Length const& reference_value);
|
|
|
|
|
static Length resolve_calculated(NonnullRefPtr<CalculatedStyleValue const> const&, Layout::Node const&, CSSPixels reference_value);
|
2024-08-02 09:28:24 -03:00
|
|
|
|
2019-07-01 12:17:32 -03:00
|
|
|
private:
|
2024-03-02 07:17:06 -03:00
|
|
|
[[nodiscard]] CSSPixels to_px_slow_case(Layout::Node const&) const;
|
|
|
|
|
|
2025-09-02 09:48:49 -03:00
|
|
|
LengthUnit m_unit;
|
2023-05-24 05:50:57 -03:00
|
|
|
double m_value { 0 };
|
2019-07-01 12:17:32 -03:00
|
|
|
};
|
2019-08-18 03:09:56 -03:00
|
|
|
|
2025-08-28 09:40:39 -03:00
|
|
|
class LengthOrAuto {
|
|
|
|
|
public:
|
|
|
|
|
LengthOrAuto(Length length)
|
2025-09-01 10:03:25 -03:00
|
|
|
: m_length(move(length))
|
2025-08-28 09:40:39 -03:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static LengthOrAuto make_auto() { return LengthOrAuto { OptionalNone {} }; }
|
|
|
|
|
|
|
|
|
|
bool is_length() const { return m_length.has_value(); }
|
|
|
|
|
bool is_auto() const { return !m_length.has_value(); }
|
|
|
|
|
|
|
|
|
|
Length const& length() const { return m_length.value(); }
|
|
|
|
|
|
|
|
|
|
String to_string(SerializationMode mode = SerializationMode::Normal) const
|
|
|
|
|
{
|
|
|
|
|
if (is_auto())
|
|
|
|
|
return "auto"_string;
|
|
|
|
|
return m_length->to_string(mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CSSPixels to_px_or_zero(Layout::Node const& node) const
|
|
|
|
|
{
|
|
|
|
|
if (is_auto())
|
|
|
|
|
return 0;
|
|
|
|
|
return m_length->to_px(node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool operator==(LengthOrAuto const&) const = default;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
explicit LengthOrAuto(Optional<Length> maybe_length)
|
|
|
|
|
: m_length(move(maybe_length))
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Optional<Length> m_length;
|
|
|
|
|
};
|
|
|
|
|
|
2020-03-07 06:27:02 -03:00
|
|
|
}
|
2022-01-19 14:30:29 -03:00
|
|
|
|
|
|
|
|
template<>
|
|
|
|
|
struct AK::Formatter<Web::CSS::Length> : Formatter<StringView> {
|
|
|
|
|
ErrorOr<void> format(FormatBuilder& builder, Web::CSS::Length const& length)
|
|
|
|
|
{
|
2023-08-22 08:25:30 -03:00
|
|
|
return Formatter<StringView>::format(builder, length.to_string());
|
2022-01-19 14:30:29 -03:00
|
|
|
}
|
|
|
|
|
};
|
2025-08-28 09:40:39 -03:00
|
|
|
|
|
|
|
|
template<>
|
|
|
|
|
struct AK::Formatter<Web::CSS::LengthOrAuto> : Formatter<StringView> {
|
|
|
|
|
ErrorOr<void> format(FormatBuilder& builder, Web::CSS::LengthOrAuto const& length_or_auto)
|
|
|
|
|
{
|
|
|
|
|
return Formatter<StringView>::format(builder, length_or_auto.to_string());
|
|
|
|
|
}
|
|
|
|
|
};
|