2022-11-08 17:37:49 +00:00
|
|
|
/*
|
2023-07-23 01:09:39 +02:00
|
|
|
* Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
|
|
|
* Copyright (c) 2012-2023, Apple Inc. All rights reserved.
|
2022-11-08 17:37:49 +00:00
|
|
|
* Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <AK/Concepts.h>
|
|
|
|
#include <AK/DistinctNumeric.h>
|
|
|
|
#include <AK/Traits.h>
|
|
|
|
#include <LibGfx/Forward.h>
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
namespace Web {
|
|
|
|
|
|
|
|
/// DevicePixels: A position or length on the physical display.
|
|
|
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, DevicePixels, Arithmetic, CastToUnderlying, Comparison, Increment);
|
|
|
|
|
2022-12-14 10:52:29 +00:00
|
|
|
template<Integral T>
|
2022-11-08 17:37:49 +00:00
|
|
|
constexpr bool operator==(DevicePixels left, T right) { return left.value() == right; }
|
|
|
|
|
2022-12-14 10:52:29 +00:00
|
|
|
template<Integral T>
|
2022-11-08 17:37:49 +00:00
|
|
|
constexpr bool operator!=(DevicePixels left, T right) { return left.value() != right; }
|
|
|
|
|
2022-12-14 10:52:29 +00:00
|
|
|
template<Integral T>
|
2022-11-08 17:37:49 +00:00
|
|
|
constexpr bool operator>(DevicePixels left, T right) { return left.value() > right; }
|
|
|
|
|
2022-12-14 10:52:29 +00:00
|
|
|
template<Integral T>
|
2022-11-08 17:37:49 +00:00
|
|
|
constexpr bool operator<(DevicePixels left, T right) { return left.value() < right; }
|
|
|
|
|
2022-12-14 10:52:29 +00:00
|
|
|
template<Integral T>
|
2022-11-08 17:37:49 +00:00
|
|
|
constexpr bool operator>=(DevicePixels left, T right) { return left.value() >= right; }
|
|
|
|
|
2022-12-14 10:52:29 +00:00
|
|
|
template<Integral T>
|
2022-11-08 17:37:49 +00:00
|
|
|
constexpr bool operator<=(DevicePixels left, T right) { return left.value() <= right; }
|
|
|
|
|
2022-12-14 10:52:29 +00:00
|
|
|
template<Integral T>
|
2022-11-08 17:37:49 +00:00
|
|
|
constexpr DevicePixels operator*(DevicePixels left, T right) { return left.value() * right; }
|
2022-12-14 10:52:29 +00:00
|
|
|
template<Integral T>
|
2022-11-08 17:37:49 +00:00
|
|
|
constexpr DevicePixels operator*(T left, DevicePixels right) { return right * left; }
|
|
|
|
|
2022-12-14 10:52:29 +00:00
|
|
|
template<Integral T>
|
2022-11-08 17:37:49 +00:00
|
|
|
constexpr DevicePixels operator/(DevicePixels left, T right) { return left.value() / right; }
|
|
|
|
|
2022-12-14 10:52:29 +00:00
|
|
|
template<Integral T>
|
2022-11-08 17:37:49 +00:00
|
|
|
constexpr DevicePixels operator%(DevicePixels left, T right) { return left.value() % right; }
|
|
|
|
|
|
|
|
/// CSSPixels: A position or length in CSS "reference pixels", independent of zoom or screen DPI.
|
|
|
|
/// See https://www.w3.org/TR/css-values-3/#reference-pixel
|
2023-06-12 21:37:35 +03:00
|
|
|
class CSSPixels {
|
|
|
|
public:
|
2023-07-23 01:09:39 +02:00
|
|
|
CSSPixels() = default;
|
|
|
|
CSSPixels(int value);
|
|
|
|
CSSPixels(unsigned int value);
|
|
|
|
CSSPixels(unsigned long value);
|
|
|
|
CSSPixels(float value);
|
|
|
|
CSSPixels(double value);
|
2023-06-12 21:37:35 +03:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
float to_float() const;
|
|
|
|
double to_double() const;
|
|
|
|
int to_int() const;
|
2023-06-12 21:37:35 +03:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
inline int raw_value() const { return m_value; }
|
|
|
|
inline void set_raw_value(int value) { m_value = value; }
|
2023-06-12 21:37:35 +03:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
bool might_be_saturated() const;
|
2023-06-12 21:37:35 +03:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
bool operator==(CSSPixels const& other) const;
|
2023-06-12 21:37:35 +03:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
explicit operator double() const { return to_double(); }
|
2023-06-12 21:37:35 +03:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
CSSPixels& operator++();
|
|
|
|
CSSPixels& operator--();
|
2023-06-12 21:37:35 +03:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
int operator<=>(CSSPixels const& other) const;
|
2023-06-12 21:37:35 +03:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
CSSPixels operator+() const;
|
|
|
|
CSSPixels operator-() const;
|
2023-06-12 21:37:35 +03:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
CSSPixels operator+(CSSPixels const& other) const;
|
|
|
|
CSSPixels operator-(CSSPixels const& other) const;
|
|
|
|
CSSPixels operator*(CSSPixels const& other) const;
|
|
|
|
CSSPixels operator/(CSSPixels const& other) const;
|
2023-06-12 21:37:35 +03:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
CSSPixels& operator+=(CSSPixels const& other);
|
|
|
|
CSSPixels& operator-=(CSSPixels const& other);
|
|
|
|
CSSPixels& operator*=(CSSPixels const& other);
|
|
|
|
CSSPixels& operator/=(CSSPixels const& other);
|
2023-06-12 21:37:35 +03:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
CSSPixels abs() const;
|
2023-06-12 21:37:35 +03:00
|
|
|
|
|
|
|
private:
|
2023-07-23 01:09:39 +02:00
|
|
|
i32 m_value { 0 };
|
2023-06-12 21:37:35 +03:00
|
|
|
};
|
2022-11-08 17:37:49 +00:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
inline bool operator==(CSSPixels left, int right) { return left == CSSPixels(right); }
|
|
|
|
inline bool operator==(CSSPixels left, float right) { return left.to_float() == right; }
|
|
|
|
inline bool operator==(CSSPixels left, double right) { return left.to_double() == right; }
|
2022-11-08 17:37:49 +00:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
inline bool operator>(CSSPixels left, int right) { return left > CSSPixels(right); }
|
|
|
|
inline bool operator>(CSSPixels left, float right) { return left.to_float() > right; }
|
|
|
|
inline bool operator>(CSSPixels left, double right) { return left.to_double() > right; }
|
2022-11-08 17:37:49 +00:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
inline bool operator<(CSSPixels left, int right) { return left < CSSPixels(right); }
|
|
|
|
inline bool operator<(CSSPixels left, float right) { return left.to_float() < right; }
|
|
|
|
inline bool operator<(CSSPixels left, double right) { return left.to_double() < right; }
|
2022-11-08 17:37:49 +00:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
inline CSSPixels operator*(CSSPixels left, int right) { return left * CSSPixels(right); }
|
|
|
|
inline CSSPixels operator*(CSSPixels left, unsigned long right) { return left * CSSPixels(right); }
|
|
|
|
inline float operator*(CSSPixels left, float right) { return left.to_float() * right; }
|
|
|
|
inline double operator*(CSSPixels left, double right) { return left.to_double() * right; }
|
2023-06-12 21:37:35 +03:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
inline CSSPixels operator*(int left, CSSPixels right) { return right * CSSPixels(left); }
|
|
|
|
inline CSSPixels operator*(unsigned long left, CSSPixels right) { return right * CSSPixels(left); }
|
|
|
|
inline float operator*(float left, CSSPixels right) { return right.to_float() * left; }
|
|
|
|
inline double operator*(double left, CSSPixels right) { return right.to_double() * left; }
|
2022-11-08 17:37:49 +00:00
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
inline CSSPixels operator/(CSSPixels left, int right) { return left / CSSPixels(right); }
|
|
|
|
inline CSSPixels operator/(CSSPixels left, unsigned long right) { return left / CSSPixels(right); }
|
|
|
|
inline float operator/(CSSPixels left, float right) { return left.to_float() / right; }
|
|
|
|
inline double operator/(CSSPixels left, double right) { return left.to_double() / right; }
|
2022-11-08 17:37:49 +00:00
|
|
|
|
|
|
|
using CSSPixelLine = Gfx::Line<CSSPixels>;
|
|
|
|
using CSSPixelPoint = Gfx::Point<CSSPixels>;
|
|
|
|
using CSSPixelRect = Gfx::Rect<CSSPixels>;
|
|
|
|
using CSSPixelSize = Gfx::Size<CSSPixels>;
|
|
|
|
|
|
|
|
using DevicePixelLine = Gfx::Line<DevicePixels>;
|
|
|
|
using DevicePixelPoint = Gfx::Point<DevicePixels>;
|
|
|
|
using DevicePixelRect = Gfx::Rect<DevicePixels>;
|
|
|
|
using DevicePixelSize = Gfx::Size<DevicePixels>;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
inline Web::CSSPixels abs(Web::CSSPixels const& value)
|
2022-11-08 17:37:49 +00:00
|
|
|
{
|
2023-07-23 01:09:39 +02:00
|
|
|
return value.abs();
|
2022-11-08 17:37:49 +00:00
|
|
|
}
|
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
constexpr Web::CSSPixels floor(Web::CSSPixels const& value)
|
2022-11-08 17:37:49 +00:00
|
|
|
{
|
2023-07-23 01:09:39 +02:00
|
|
|
// FIXME: Actually floor value
|
|
|
|
return value;
|
2022-11-08 17:37:49 +00:00
|
|
|
}
|
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
constexpr Web::CSSPixels ceil(Web::CSSPixels const& value)
|
2022-11-08 17:37:49 +00:00
|
|
|
{
|
2023-07-23 01:09:39 +02:00
|
|
|
// FIXME: Actually ceil value
|
|
|
|
return value;
|
2022-11-08 17:37:49 +00:00
|
|
|
}
|
|
|
|
|
2023-07-23 01:09:39 +02:00
|
|
|
constexpr Web::CSSPixels round(Web::CSSPixels const& value)
|
2022-11-08 17:37:49 +00:00
|
|
|
{
|
2023-07-23 01:09:39 +02:00
|
|
|
// FIXME: Actually round value
|
|
|
|
return value;
|
2022-11-08 17:37:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
constexpr Web::DevicePixels abs(Web::DevicePixels const& value)
|
|
|
|
{
|
|
|
|
return AK::abs(value.value());
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace AK {
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct Traits<Web::CSSPixels> : public GenericTraits<Web::CSSPixels> {
|
|
|
|
static unsigned hash(Web::CSSPixels const& key)
|
|
|
|
{
|
2023-06-12 21:37:35 +03:00
|
|
|
VERIFY(isfinite(key.to_double()));
|
|
|
|
return Traits<double>::hash(key.to_double());
|
2022-11-08 17:37:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool equals(Web::CSSPixels const& a, Web::CSSPixels const& b)
|
|
|
|
{
|
|
|
|
return a == b;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct Traits<Web::DevicePixels> : public GenericTraits<Web::DevicePixels> {
|
|
|
|
static unsigned hash(Web::DevicePixels const& key)
|
|
|
|
{
|
2023-01-20 15:23:17 -05:00
|
|
|
return Traits<Web::DevicePixels::Type>::hash(key.value());
|
2022-11-08 17:37:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool equals(Web::DevicePixels const& a, Web::DevicePixels const& b)
|
|
|
|
{
|
|
|
|
return a == b;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
2023-06-12 21:37:35 +03:00
|
|
|
struct Formatter<Web::CSSPixels> : Formatter<double> {
|
2022-11-08 17:37:49 +00:00
|
|
|
ErrorOr<void> format(FormatBuilder& builder, Web::CSSPixels const& value)
|
|
|
|
{
|
2023-06-12 21:37:35 +03:00
|
|
|
return Formatter<double>::format(builder, value.to_double());
|
2022-11-08 17:37:49 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
2023-01-20 15:23:17 -05:00
|
|
|
struct Formatter<Web::DevicePixels> : Formatter<Web::DevicePixels::Type> {
|
2022-11-08 17:37:49 +00:00
|
|
|
ErrorOr<void> format(FormatBuilder& builder, Web::DevicePixels const& value)
|
|
|
|
{
|
2023-01-20 15:23:17 -05:00
|
|
|
return Formatter<Web::DevicePixels::Type>::format(builder, value.value());
|
2022-11-08 17:37:49 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|