mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
7c4b0b0389
Ignoring Size for a second, we currently have: Rect::scale_by Rect::scaled Point::scale_by Point::scaled In Size, before this patch, we have: Size::scale_by Size::scaled_by This aligns Size to use the same method name as Rect and Point. While subjectively providing API symmetry, this is mostly to allow using this method in templated helpers without caring what the exact underlying type is.
222 lines
5.7 KiB
C++
222 lines
5.7 KiB
C++
/*
|
|
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Format.h>
|
|
#include <LibGfx/Orientation.h>
|
|
#include <LibGfx/Point.h>
|
|
#include <LibIPC/Forward.h>
|
|
|
|
namespace Gfx {
|
|
|
|
template<typename T>
|
|
class Size {
|
|
public:
|
|
constexpr Size() = default;
|
|
|
|
constexpr Size(T w, T h)
|
|
: m_width(w)
|
|
, m_height(h)
|
|
{
|
|
}
|
|
|
|
template<typename U>
|
|
constexpr Size(U width, U height)
|
|
: m_width(width)
|
|
, m_height(height)
|
|
{
|
|
}
|
|
|
|
template<typename U>
|
|
explicit constexpr Size(Size<U> const& other)
|
|
: m_width(other.width())
|
|
, m_height(other.height())
|
|
{
|
|
}
|
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr T width() const { return m_width; }
|
|
[[nodiscard]] ALWAYS_INLINE constexpr T height() const { return m_height; }
|
|
[[nodiscard]] ALWAYS_INLINE constexpr T area() const { return width() * height(); }
|
|
|
|
ALWAYS_INLINE constexpr void set_width(T w) { m_width = w; }
|
|
ALWAYS_INLINE constexpr void set_height(T h) { m_height = h; }
|
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr bool is_empty() const { return m_width <= 0 || m_height <= 0; }
|
|
|
|
constexpr void scale_by(T dx, T dy)
|
|
{
|
|
m_width *= dx;
|
|
m_height *= dy;
|
|
}
|
|
|
|
constexpr void transform_by(AffineTransform const& transform) { *this = transform.map(*this); }
|
|
|
|
ALWAYS_INLINE constexpr void scale_by(T dboth) { scale_by(dboth, dboth); }
|
|
ALWAYS_INLINE constexpr void scale_by(Point<T> const& s) { scale_by(s.x(), s.y()); }
|
|
|
|
[[nodiscard]] constexpr Size scaled(T dx, T dy) const
|
|
{
|
|
Size<T> size = *this;
|
|
size.scale_by(dx, dy);
|
|
return size;
|
|
}
|
|
|
|
[[nodiscard]] constexpr Size scaled(T dboth) const
|
|
{
|
|
Size<T> size = *this;
|
|
size.scale_by(dboth);
|
|
return size;
|
|
}
|
|
|
|
[[nodiscard]] constexpr Size scaled(Point<T> const& s) const
|
|
{
|
|
Size<T> size = *this;
|
|
size.scale_by(s);
|
|
return size;
|
|
}
|
|
|
|
[[nodiscard]] constexpr Size transformed_by(AffineTransform const& transform) const
|
|
{
|
|
Size<T> size = *this;
|
|
size.transform_by(transform);
|
|
return size;
|
|
}
|
|
|
|
[[nodiscard]] constexpr float aspect_ratio() const
|
|
{
|
|
VERIFY(height() != 0);
|
|
return static_cast<float>(width()) / static_cast<float>(height());
|
|
}
|
|
|
|
// Horizontal means preserve the width, Vertical means preserve the height.
|
|
[[nodiscard]] constexpr Size<T> match_aspect_ratio(float aspect_ratio, Orientation side_to_preserve) const
|
|
{
|
|
VERIFY(aspect_ratio != 0.0f);
|
|
auto matched = *this;
|
|
auto height_corresponding_to_width = static_cast<T>(static_cast<float>(width()) / aspect_ratio);
|
|
auto width_corresponding_to_height = static_cast<T>(static_cast<float>(height()) * aspect_ratio);
|
|
|
|
switch (side_to_preserve) {
|
|
case Orientation::Vertical:
|
|
matched.m_width = width_corresponding_to_height;
|
|
break;
|
|
case Orientation::Horizontal:
|
|
matched.m_height = height_corresponding_to_width;
|
|
break;
|
|
}
|
|
return matched;
|
|
}
|
|
|
|
template<typename U>
|
|
[[nodiscard]] constexpr bool contains(Size<U> const& other) const
|
|
{
|
|
return other.m_width <= m_width && other.m_height <= m_height;
|
|
}
|
|
|
|
template<class U>
|
|
[[nodiscard]] constexpr bool operator==(Size<U> const& other) const
|
|
{
|
|
return width() == other.width() && height() == other.height();
|
|
}
|
|
|
|
constexpr Size<T>& operator-=(Size<T> const& other)
|
|
{
|
|
m_width -= other.m_width;
|
|
m_height -= other.m_height;
|
|
return *this;
|
|
}
|
|
|
|
Size<T>& operator+=(Size<T> const& other)
|
|
{
|
|
m_width += other.m_width;
|
|
m_height += other.m_height;
|
|
return *this;
|
|
}
|
|
|
|
[[nodiscard]] constexpr Size<T> operator*(T factor) const { return { m_width * factor, m_height * factor }; }
|
|
|
|
constexpr Size<T>& operator*=(T factor)
|
|
{
|
|
m_width *= factor;
|
|
m_height *= factor;
|
|
return *this;
|
|
}
|
|
|
|
[[nodiscard]] constexpr T primary_size_for_orientation(Orientation orientation) const
|
|
{
|
|
return orientation == Orientation::Vertical ? height() : width();
|
|
}
|
|
|
|
constexpr void set_primary_size_for_orientation(Orientation orientation, T value)
|
|
{
|
|
if (orientation == Orientation::Vertical) {
|
|
set_height(value);
|
|
} else {
|
|
set_width(value);
|
|
}
|
|
}
|
|
|
|
[[nodiscard]] constexpr T secondary_size_for_orientation(Orientation orientation) const
|
|
{
|
|
return orientation == Orientation::Vertical ? width() : height();
|
|
}
|
|
|
|
constexpr void set_secondary_size_for_orientation(Orientation orientation, T value)
|
|
{
|
|
if (orientation == Orientation::Vertical) {
|
|
set_width(value);
|
|
} else {
|
|
set_height(value);
|
|
}
|
|
}
|
|
|
|
template<typename U>
|
|
requires(!IsSame<T, U>)
|
|
[[nodiscard]] ALWAYS_INLINE constexpr Size<U> to_type() const
|
|
{
|
|
return Size<U>(*this);
|
|
}
|
|
|
|
[[nodiscard]] DeprecatedString to_deprecated_string() const;
|
|
|
|
template<Integral I>
|
|
[[nodiscard]] Size<I> to_rounded() const
|
|
{
|
|
return Size<I>(round_to<I>(width()), round_to<I>(height()));
|
|
}
|
|
|
|
private:
|
|
T m_width { 0 };
|
|
T m_height { 0 };
|
|
};
|
|
|
|
using IntSize = Size<int>;
|
|
using FloatSize = Size<float>;
|
|
|
|
}
|
|
|
|
namespace AK {
|
|
|
|
template<typename T>
|
|
struct Formatter<Gfx::Size<T>> : Formatter<FormatString> {
|
|
ErrorOr<void> format(FormatBuilder& builder, Gfx::Size<T> const& value)
|
|
{
|
|
return Formatter<FormatString>::format(builder, "[{}x{}]"sv, value.width(), value.height());
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
namespace IPC {
|
|
|
|
template<>
|
|
ErrorOr<void> encode(Encoder&, Gfx::IntSize const&);
|
|
|
|
template<>
|
|
ErrorOr<Gfx::IntSize> decode(Decoder&);
|
|
|
|
}
|