summaryrefslogtreecommitdiff
path: root/Libraries/LibGfx
diff options
context:
space:
mode:
authorMatthew Olsson <matthewcolsson@gmail.com>2020-07-25 21:31:47 -0700
committerAndreas Kling <kling@serenityos.org>2020-07-27 01:06:26 +0200
commit335916d8db8421565c4cc232b36a397d6a7fb864 (patch)
treecbc8215d0f07d1eb014f0b2287d3d4f5aa16419c /Libraries/LibGfx
parent7a1c328417972efc33af8bc7cbc745340369a8f0 (diff)
downloadserenity-335916d8db8421565c4cc232b36a397d6a7fb864.zip
LibGfx: Templatize Point, Size, and Rect
Diffstat (limited to 'Libraries/LibGfx')
-rw-r--r--Libraries/LibGfx/AffineTransform.cpp23
-rw-r--r--Libraries/LibGfx/AffineTransform.h12
-rw-r--r--Libraries/LibGfx/CMakeLists.txt1
-rw-r--r--Libraries/LibGfx/FloatRect.cpp135
-rw-r--r--Libraries/LibGfx/FloatRect.h335
-rw-r--r--Libraries/LibGfx/FloatSize.h125
-rw-r--r--Libraries/LibGfx/Forward.h24
-rw-r--r--Libraries/LibGfx/Painter.cpp7
-rw-r--r--Libraries/LibGfx/Path.cpp2
-rw-r--r--Libraries/LibGfx/Path.h3
-rw-r--r--Libraries/LibGfx/Point.cpp27
-rw-r--r--Libraries/LibGfx/Point.h149
-rw-r--r--Libraries/LibGfx/Rect.cpp41
-rw-r--r--Libraries/LibGfx/Rect.h216
-rw-r--r--Libraries/LibGfx/ShareableBitmap.cpp1
-rw-r--r--Libraries/LibGfx/ShareableBitmap.h2
-rw-r--r--Libraries/LibGfx/Size.cpp9
-rw-r--r--Libraries/LibGfx/Size.h79
18 files changed, 380 insertions, 811 deletions
diff --git a/Libraries/LibGfx/AffineTransform.cpp b/Libraries/LibGfx/AffineTransform.cpp
index 77738c25ed..29236b83f0 100644
--- a/Libraries/LibGfx/AffineTransform.cpp
+++ b/Libraries/LibGfx/AffineTransform.cpp
@@ -27,7 +27,6 @@
#include <AK/LogStream.h>
#include <AK/Optional.h>
#include <LibGfx/AffineTransform.h>
-#include <LibGfx/FloatRect.h>
#include <LibGfx/Rect.h>
namespace Gfx {
@@ -97,37 +96,36 @@ void AffineTransform::map(float unmapped_x, float unmapped_y, float& mapped_x, f
mapped_y = (m_values[1] * unmapped_x + m_values[3] * unmapped_y + m_values[5]);
}
+template<>
IntPoint AffineTransform::map(const IntPoint& point) const
{
float mapped_x;
float mapped_y;
map(point.x(), point.y(), mapped_x, mapped_y);
- return IntPoint(roundf(mapped_x), roundf(mapped_y));
+ return { roundf(mapped_x), roundf(mapped_y) };
}
+template<>
FloatPoint AffineTransform::map(const FloatPoint& point) const
{
float mapped_x;
float mapped_y;
map(point.x(), point.y(), mapped_x, mapped_y);
- return FloatPoint(mapped_x, mapped_y);
+ return { mapped_x, mapped_y };
}
+template<>
IntSize AffineTransform::map(const IntSize& size) const
{
- return IntSize(roundf(size.width() * x_scale()), roundf(y_scale()));
+ return { roundf(size.width() * x_scale()), roundf(size.height() * y_scale()) };
}
+template<>
FloatSize AffineTransform::map(const FloatSize& size) const
{
return { size.width() * x_scale(), size.height() * y_scale() };
}
-IntRect AffineTransform::map(const IntRect& rect) const
-{
- return enclosing_int_rect(map(FloatRect(rect)));
-}
-
template<typename T>
static T smallest_of(T p1, T p2, T p3, T p4)
{
@@ -140,6 +138,7 @@ static T largest_of(T p1, T p2, T p3, T p4)
return max(max(p1, p2), max(p3, p4));
}
+template<>
FloatRect AffineTransform::map(const FloatRect& rect) const
{
FloatPoint p1 = map(rect.top_left());
@@ -153,6 +152,12 @@ FloatRect AffineTransform::map(const FloatRect& rect) const
return { left, top, right - left, bottom - top };
}
+template<>
+IntRect AffineTransform::map(const IntRect& rect) const
+{
+ return enclosing_int_rect(map(FloatRect(rect)));
+}
+
const LogStream& operator<<(const LogStream& stream, const AffineTransform& value)
{
if (value.is_identity())
diff --git a/Libraries/LibGfx/AffineTransform.h b/Libraries/LibGfx/AffineTransform.h
index 0a3613171d..41334eb138 100644
--- a/Libraries/LibGfx/AffineTransform.h
+++ b/Libraries/LibGfx/AffineTransform.h
@@ -48,14 +48,14 @@ public:
void map(float unmapped_x, float unmapped_y, float& mapped_x, float& mapped_y) const;
- IntPoint map(const IntPoint&) const;
- FloatPoint map(const FloatPoint&) const;
+ template<typename T>
+ Point<T> map(const Point<T>&) const;
- IntSize map(const IntSize&) const;
- FloatSize map(const FloatSize&) const;
+ template<typename T>
+ Size<T> map(const Size<T>&) const;
- IntRect map(const IntRect&) const;
- FloatRect map(const FloatRect&) const;
+ template<typename T>
+ Rect<T> map(const Rect<T>&) const;
float a() const { return m_values[0]; }
float b() const { return m_values[1]; }
diff --git a/Libraries/LibGfx/CMakeLists.txt b/Libraries/LibGfx/CMakeLists.txt
index 1a620fac16..44faca4696 100644
--- a/Libraries/LibGfx/CMakeLists.txt
+++ b/Libraries/LibGfx/CMakeLists.txt
@@ -6,7 +6,6 @@ set(SOURCES
Color.cpp
DisjointRectSet.cpp
Emoji.cpp
- FloatRect.cpp
Font.cpp
GIFLoader.cpp
ICOLoader.cpp
diff --git a/Libraries/LibGfx/FloatRect.cpp b/Libraries/LibGfx/FloatRect.cpp
deleted file mode 100644
index 0a50961555..0000000000
--- a/Libraries/LibGfx/FloatRect.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <AK/StdLibExtras.h>
-#include <AK/String.h>
-#include <AK/Vector.h>
-#include <LibGfx/FloatRect.h>
-#include <LibIPC/Decoder.h>
-
-namespace Gfx {
-
-void FloatRect::intersect(const FloatRect& other)
-{
- int l = max(left(), other.left());
- int r = min(right(), other.right());
- int t = max(top(), other.top());
- int b = min(bottom(), other.bottom());
-
- if (l > r || t > b) {
- m_location = {};
- m_size = {};
- return;
- }
-
- m_location.set_x(l);
- m_location.set_y(t);
- m_size.set_width((r - l) + 1);
- m_size.set_height((b - t) + 1);
-}
-
-FloatRect FloatRect::united(const FloatRect& other) const
-{
- if (is_null())
- return other;
- if (other.is_null())
- return *this;
- FloatRect rect;
- rect.set_left(min(left(), other.left()));
- rect.set_top(min(top(), other.top()));
- rect.set_right(max(right(), other.right()));
- rect.set_bottom(max(bottom(), other.bottom()));
- return rect;
-}
-
-Vector<FloatRect, 4> FloatRect::shatter(const FloatRect& hammer) const
-{
- Vector<FloatRect, 4> pieces;
- if (!intersects(hammer)) {
- pieces.unchecked_append(*this);
- return pieces;
- }
- FloatRect top_shard {
- x(),
- y(),
- width(),
- hammer.y() - y()
- };
- FloatRect bottom_shard {
- x(),
- hammer.y() + hammer.height(),
- width(),
- (y() + height()) - (hammer.y() + hammer.height())
- };
- FloatRect left_shard {
- x(),
- max(hammer.y(), y()),
- hammer.x() - x(),
- min((hammer.y() + hammer.height()), (y() + height())) - max(hammer.y(), y())
- };
- FloatRect right_shard {
- hammer.x() + hammer.width(),
- max(hammer.y(), y()),
- right() - hammer.right(),
- min((hammer.y() + hammer.height()), (y() + height())) - max(hammer.y(), y())
- };
- if (!top_shard.is_empty())
- pieces.unchecked_append(top_shard);
- if (!bottom_shard.is_empty())
- pieces.unchecked_append(bottom_shard);
- if (!left_shard.is_empty())
- pieces.unchecked_append(left_shard);
- if (!right_shard.is_empty())
- pieces.unchecked_append(right_shard);
-
- return pieces;
-}
-
-void FloatRect::align_within(const FloatRect& other, TextAlignment alignment)
-{
- switch (alignment) {
- case TextAlignment::Center:
- center_within(other);
- return;
- case TextAlignment::TopLeft:
- set_location(other.location());
- return;
- case TextAlignment::TopRight:
- set_x(other.x() + other.width() - width());
- set_y(other.y());
- return;
- case TextAlignment::CenterLeft:
- set_x(other.x());
- center_vertically_within(other);
- return;
- case TextAlignment::CenterRight:
- set_x(other.x() + other.width() - width());
- center_vertically_within(other);
- return;
- }
-}
-
-}
diff --git a/Libraries/LibGfx/FloatRect.h b/Libraries/LibGfx/FloatRect.h
deleted file mode 100644
index 3908dd8318..0000000000
--- a/Libraries/LibGfx/FloatRect.h
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include <AK/LogStream.h>
-#include <AK/String.h>
-#include <LibGfx/FloatPoint.h>
-#include <LibGfx/FloatSize.h>
-#include <LibGfx/Orientation.h>
-#include <LibGfx/Rect.h>
-#include <LibGfx/TextAlignment.h>
-#include <math.h>
-
-namespace Gfx {
-
-class FloatRect {
-public:
- FloatRect() {}
- FloatRect(float x, float y, float width, float height)
- : m_location(x, y)
- , m_size(width, height)
- {
- }
- FloatRect(const FloatPoint& location, const FloatSize& size)
- : m_location(location)
- , m_size(size)
- {
- }
- FloatRect(const FloatRect& other)
- : m_location(other.m_location)
- , m_size(other.m_size)
- {
- }
-
- explicit FloatRect(const IntRect& other)
- : FloatRect((FloatPoint)other.location(), (FloatSize)other.size())
- {
- }
-
- bool is_null() const
- {
- return width() == 0 && height() == 0;
- }
-
- bool is_empty() const
- {
- return width() <= 0 || height() <= 0;
- }
-
- void move_by(float dx, float dy)
- {
- m_location.move_by(dx, dy);
- }
-
- void move_by(const FloatPoint& delta)
- {
- m_location.move_by(delta);
- }
-
- FloatPoint center() const
- {
- return { x() + width() / 2, y() + height() / 2 };
- }
-
- void set_location(const FloatPoint& location)
- {
- m_location = location;
- }
-
- void set_size(const FloatSize& size)
- {
- m_size = size;
- }
-
- void set_size(float width, float height)
- {
- m_size.set_width(width);
- m_size.set_height(height);
- }
-
- void inflate(float w, float h)
- {
- set_x(x() - w / 2);
- set_width(width() + w);
- set_y(y() - h / 2);
- set_height(height() + h);
- }
-
- void shrink(float w, float h)
- {
- set_x(x() + w / 2);
- set_width(width() - w);
- set_y(y() + h / 2);
- set_height(height() - h);
- }
-
- FloatRect shrunken(float w, float h) const
- {
- FloatRect rect = *this;
- rect.shrink(w, h);
- return rect;
- }
-
- FloatRect inflated(float w, float h) const
- {
- FloatRect rect = *this;
- rect.inflate(w, h);
- return rect;
- }
-
- FloatRect translated(float dx, float dy) const
- {
- FloatRect rect = *this;
- rect.move_by(dx, dy);
- return rect;
- }
-
- FloatRect translated(const FloatPoint& delta) const
- {
- FloatRect rect = *this;
- rect.move_by(delta);
- return rect;
- }
-
- bool contains_vertically(float y) const
- {
- return y >= top() && y <= bottom();
- }
-
- bool contains_horizontally(float x) const
- {
- return x >= left() && x <= right();
- }
-
- bool contains(float x, float y) const
- {
- return x >= m_location.x() && x <= right() && y >= m_location.y() && y <= bottom();
- }
-
- bool contains(const FloatPoint& point) const
- {
- return contains(point.x(), point.y());
- }
-
- bool contains(const FloatRect& other) const
- {
- return left() <= other.left()
- && right() >= other.right()
- && top() <= other.top()
- && bottom() >= other.bottom();
- }
-
- float primary_offset_for_orientation(Orientation orientation) const { return m_location.primary_offset_for_orientation(orientation); }
- void set_primary_offset_for_orientation(Orientation orientation, float value) { m_location.set_primary_offset_for_orientation(orientation, value); }
- float secondary_offset_for_orientation(Orientation orientation) const { return m_location.secondary_offset_for_orientation(orientation); }
- void set_secondary_offset_for_orientation(Orientation orientation, float value) { m_location.set_secondary_offset_for_orientation(orientation, value); }
-
- float primary_size_for_orientation(Orientation orientation) const { return m_size.primary_size_for_orientation(orientation); }
- float secondary_size_for_orientation(Orientation orientation) const { return m_size.secondary_size_for_orientation(orientation); }
- void set_primary_size_for_orientation(Orientation orientation, float value) { m_size.set_primary_size_for_orientation(orientation, value); }
- void set_secondary_size_for_orientation(Orientation orientation, float value) { m_size.set_secondary_size_for_orientation(orientation, value); }
-
- float first_edge_for_orientation(Orientation orientation) const
- {
- if (orientation == Orientation::Vertical)
- return top();
- return left();
- }
-
- float last_edge_for_orientation(Orientation orientation) const
- {
- if (orientation == Orientation::Vertical)
- return bottom();
- return right();
- }
-
- float left() const { return x(); }
- float right() const { return x() + width() - 1; }
- float top() const { return y(); }
- float bottom() const { return y() + height() - 1; }
-
- void set_left(float left)
- {
- set_x(left);
- }
-
- void set_top(float top)
- {
- set_y(top);
- }
-
- void set_right(float right)
- {
- set_width(right - x() + 1);
- }
-
- void set_bottom(float bottom)
- {
- set_height(bottom - y() + 1);
- }
-
- void set_right_without_resize(float new_right)
- {
- float delta = new_right - right();
- move_by(delta, 0);
- }
-
- void set_bottom_without_resize(float new_bottom)
- {
- float delta = new_bottom - bottom();
- move_by(0, delta);
- }
-
- bool intersects(const FloatRect& other) const
- {
- return left() <= other.right()
- && other.left() <= right()
- && top() <= other.bottom()
- && other.top() <= bottom();
- }
-
- float x() const { return location().x(); }
- float y() const { return location().y(); }
- float width() const { return m_size.width(); }
- float height() const { return m_size.height(); }
-
- void set_x(float x) { m_location.set_x(x); }
- void set_y(float y) { m_location.set_y(y); }
- void set_width(float width) { m_size.set_width(width); }
- void set_height(float height) { m_size.set_height(height); }
-
- FloatPoint location() const { return m_location; }
- FloatSize size() const { return m_size; }
-
- Vector<FloatRect, 4> shatter(const FloatRect& hammer) const;
-
- bool operator==(const FloatRect& other) const
- {
- return m_location == other.m_location
- && m_size == other.m_size;
- }
-
- void intersect(const FloatRect&);
-
- static FloatRect intersection(const FloatRect& a, const FloatRect& b)
- {
- FloatRect r(a);
- r.intersect(b);
- return r;
- }
-
- FloatRect intersected(const FloatRect& other) const
- {
- return intersection(*this, other);
- }
-
- FloatRect united(const FloatRect&) const;
-
- FloatPoint top_left() const { return { left(), top() }; }
- FloatPoint top_right() const { return { right(), top() }; }
- FloatPoint bottom_left() const { return { left(), bottom() }; }
- FloatPoint bottom_right() const { return { right(), bottom() }; }
-
- void align_within(const FloatRect&, TextAlignment);
-
- void center_within(const FloatRect& other)
- {
- center_horizontally_within(other);
- center_vertically_within(other);
- }
-
- void center_horizontally_within(const FloatRect& other)
- {
- set_x(other.center().x() - width() / 2);
- }
-
- void center_vertically_within(const FloatRect& other)
- {
- set_y(other.center().y() - height() / 2);
- }
-
- String to_string() const { return String::format("[%g,%g %gx%g]", x(), y(), width(), height()); }
-
-private:
- FloatPoint m_location;
- FloatSize m_size;
-};
-
-inline void FloatPoint::constrain(const FloatRect& rect)
-{
- if (x() < rect.left())
- set_x(rect.left());
- else if (x() > rect.right())
- set_x(rect.right());
- if (y() < rect.top())
- set_y(rect.top());
- else if (y() > rect.bottom())
- set_y(rect.bottom());
-}
-
-inline const LogStream& operator<<(const LogStream& stream, const FloatRect& value)
-{
- return stream << value.to_string();
-}
-
-inline IntRect enclosing_int_rect(const FloatRect& float_rect)
-{
- return { (int)float_rect.x(), (int)float_rect.y(), (int)ceilf(float_rect.width()), (int)ceilf(float_rect.height()) };
-}
-
-}
diff --git a/Libraries/LibGfx/FloatSize.h b/Libraries/LibGfx/FloatSize.h
deleted file mode 100644
index 1bbe2453a3..0000000000
--- a/Libraries/LibGfx/FloatSize.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include <AK/LogStream.h>
-#include <AK/String.h>
-#include <LibGfx/Orientation.h>
-#include <LibGfx/Size.h>
-
-namespace Gfx {
-
-class FloatSize {
-public:
- FloatSize() { }
- FloatSize(float w, float h)
- : m_width(w)
- , m_height(h)
- {
- }
- explicit FloatSize(const IntSize& other)
- : m_width(other.width())
- , m_height(other.height())
- {
- }
-
- bool is_null() const { return !m_width && !m_height; }
- bool is_empty() const { return m_width <= 0 || m_height <= 0; }
-
- float width() const { return m_width; }
- float height() const { return m_height; }
-
- float area() const { return width() * height(); }
-
- void set_width(float w) { m_width = w; }
- void set_height(float h) { m_height = h; }
-
- bool operator==(const FloatSize& other) const
- {
- return m_width == other.m_width && m_height == other.m_height;
- }
-
- bool operator!=(const FloatSize& other) const
- {
- return !(*this == other);
- }
-
- FloatSize& operator-=(const FloatSize& other)
- {
- m_width -= other.m_width;
- m_height -= other.m_height;
- return *this;
- }
-
- FloatSize& operator+=(const FloatSize& other)
- {
- m_width += other.m_width;
- m_height += other.m_height;
- return *this;
- }
-
- float primary_size_for_orientation(Orientation orientation) const
- {
- return orientation == Orientation::Vertical ? height() : width();
- }
-
- void set_primary_size_for_orientation(Orientation orientation, float value)
- {
- if (orientation == Orientation::Vertical)
- set_height(value);
- else
- set_width(value);
- }
-
- float secondary_size_for_orientation(Orientation orientation) const
- {
- return orientation == Orientation::Vertical ? width() : height();
- }
-
- void set_secondary_size_for_orientation(Orientation orientation, float value)
- {
- if (orientation == Orientation::Vertical)
- set_width(value);
- else
- set_height(value);
- }
-
- String to_string() const { return String::format("[%gx%g]", m_width, m_height); }
-
- IntSize to_int_size() const { return IntSize(width(), height()); }
-
-private:
- float m_width { 0 };
- float m_height { 0 };
-};
-
-inline const LogStream& operator<<(const LogStream& stream, const FloatSize& value)
-{
- return stream << value.to_string();
-}
-
-}
diff --git a/Libraries/LibGfx/Forward.h b/Libraries/LibGfx/Forward.h
index befacc8171..7d7fc2f482 100644
--- a/Libraries/LibGfx/Forward.h
+++ b/Libraries/LibGfx/Forward.h
@@ -33,9 +33,6 @@ class CharacterBitmap;
class Color;
class DisjointRectSet;
class Emoji;
-class FloatPoint;
-class FloatRect;
-class FloatSize;
class Font;
class GlyphBitmap;
class ImageDecoder;
@@ -43,14 +40,29 @@ class Painter;
class Palette;
class PaletteImpl;
class Path;
-class IntPoint;
-class IntRect;
class ShareableBitmap;
-class IntSize;
class StylePainter;
struct SystemTheme;
class Triangle;
+template<typename T>
+class Point;
+
+template<typename T>
+class Size;
+
+template<typename T>
+class Rect;
+
+using IntRect = Rect<int>;
+using FloatRect = Rect<float>;
+
+using IntPoint = Point<int>;
+using FloatPoint = Point<float>;
+
+using IntSize = Size<int>;
+using FloatSize = Size<float>;
+
enum class BitmapFormat;
enum class ColorRole;
enum class TextAlignment;
diff --git a/Libraries/LibGfx/Painter.cpp b/Libraries/LibGfx/Painter.cpp
index 770f5f03de..72cc52f029 100644
--- a/Libraries/LibGfx/Painter.cpp
+++ b/Libraries/LibGfx/Painter.cpp
@@ -40,7 +40,6 @@
#include <LibGfx/Path.h>
#include <math.h>
#include <stdio.h>
-#include <unistd.h>
#if defined(__GNUC__) && !defined(__clang__)
# pragma GCC optimize("O3")
@@ -1399,18 +1398,18 @@ void Painter::stroke_path(const Path& path, Color color, int thickness)
cursor = segment.point();
break;
case Segment::Type::LineTo:
- draw_line(cursor, segment.point(), color, thickness);
+ draw_line(cursor.to_type<int>(), segment.point().to_type<int>(), color, thickness);
cursor = segment.point();
break;
case Segment::Type::QuadraticBezierCurveTo: {
auto& through = static_cast<const QuadraticBezierCurveSegment&>(segment).through();
- draw_quadratic_bezier_curve(through, cursor, segment.point(), color, thickness);
+ draw_quadratic_bezier_curve(through.to_type<int>(), cursor.to_type<int>(), segment.point().to_type<int>(), color, thickness);
cursor = segment.point();
break;
}
case Segment::Type::EllipticalArcTo:
auto& arc = static_cast<const EllipticalArcSegment&>(segment);
- draw_elliptical_arc(cursor, segment.point(), arc.center(), arc.radii(), arc.x_axis_rotation(), arc.theta_1(), arc.theta_delta(), color, thickness);
+ draw_elliptical_arc(cursor.to_type<int>(), segment.point().to_type<int>(), arc.center().to_type<int>(), arc.radii(), arc.x_axis_rotation(), arc.theta_1(), arc.theta_delta(), color, thickness);
cursor = segment.point();
break;
}
diff --git a/Libraries/LibGfx/Path.cpp b/Libraries/LibGfx/Path.cpp
index 194ff8e982..967dd09c55 100644
--- a/Libraries/LibGfx/Path.cpp
+++ b/Libraries/LibGfx/Path.cpp
@@ -25,13 +25,11 @@
*/
#include <AK/Function.h>
-#include <AK/HashFunctions.h>
#include <AK/HashTable.h>
#include <AK/QuickSort.h>
#include <AK/StringBuilder.h>
#include <LibGfx/Painter.h>
#include <LibGfx/Path.h>
-#include <math.h>
namespace Gfx {
diff --git a/Libraries/LibGfx/Path.h b/Libraries/LibGfx/Path.h
index 3987653338..585f50fae1 100644
--- a/Libraries/LibGfx/Path.h
+++ b/Libraries/LibGfx/Path.h
@@ -29,8 +29,9 @@
#include <AK/HashMap.h>
#include <AK/NonnullRefPtrVector.h>
#include <AK/Optional.h>
+#include <AK/String.h>
#include <AK/Vector.h>
-#include <LibGfx/FloatPoint.h>
+#include <LibGfx/Point.h>
#include <LibGfx/Forward.h>
namespace Gfx {
diff --git a/Libraries/LibGfx/Point.cpp b/Libraries/LibGfx/Point.cpp
index b575dbafb5..5dba69ad00 100644
--- a/Libraries/LibGfx/Point.cpp
+++ b/Libraries/LibGfx/Point.cpp
@@ -26,26 +26,38 @@
#include <AK/String.h>
#include <LibGfx/Point.h>
-#include <LibGfx/FloatPoint.h>
+#include <LibGfx/Rect.h>
#include <LibIPC/Decoder.h>
#include <LibIPC/Encoder.h>
namespace Gfx {
-IntPoint::IntPoint(const FloatPoint& other)
- : m_x(other.x())
- , m_y(other.y())
+template<typename T>
+void Point<T>::constrain(const Rect<T>& rect)
{
+ if (x() < rect.left()) {
+ set_x(rect.left());
+ } else if (x() > rect.right()) {
+ set_x(rect.right());
+ }
+
+ if (y() < rect.top()) {
+ set_y(rect.top());
+ } else if (y() > rect.bottom()) {
+ set_y(rect.bottom());
+ }
}
+template<>
String IntPoint::to_string() const
{
return String::format("[%d,%d]", x(), y());
}
-const LogStream& operator<<(const LogStream& stream, const IntPoint& value)
+template<>
+String FloatPoint::to_string() const
{
- return stream << value.to_string();
+ return String::format("[%f,%f]", x(), y());
}
}
@@ -71,3 +83,6 @@ bool decode(Decoder& decoder, Gfx::IntPoint& point)
}
}
+
+template class Gfx::Point<int>;
+template class Gfx::Point<float>;
diff --git a/Libraries/LibGfx/Point.h b/Libraries/LibGfx/Point.h
index 59cc4d88c7..9ba78a9744 100644
--- a/Libraries/LibGfx/Point.h
+++ b/Libraries/LibGfx/Point.h
@@ -29,159 +29,206 @@
#include <AK/Forward.h>
#include <AK/StdLibExtras.h>
#include <LibGfx/Orientation.h>
+#include <LibGfx/Forward.h>
#include <LibIPC/Forward.h>
+#include <LibM/math.h>
#include <stdlib.h>
namespace Gfx {
-class IntRect;
-class FloatPoint;
-
-class IntPoint {
+template<typename T>
+class Point {
public:
- IntPoint() { }
- IntPoint(int x, int y)
+ Point() { }
+
+ Point(T x, T y)
+ : m_x(x)
+ , m_y(y)
+ {
+ }
+
+ template<typename U>
+ Point(U x, U y)
: m_x(x)
, m_y(y)
{
}
- IntPoint(const FloatPoint&);
+ template<typename U>
+ explicit Point(const Point<U>& other)
+ : m_x(other.x())
+ , m_y(other.y())
+ {
+ }
- int x() const { return m_x; }
- int y() const { return m_y; }
+ T x() const { return m_x; }
+ T y() const { return m_y; }
- void set_x(int x) { m_x = x; }
- void set_y(int y) { m_y = y; }
+ void set_x(T x) { m_x = x; }
+ void set_y(T y) { m_y = y; }
- void move_by(int dx, int dy)
+ void move_by(T dx, T dy)
{
m_x += dx;
m_y += dy;
}
- void move_by(const IntPoint& delta)
+ void move_by(const Point<T>& delta)
{
move_by(delta.x(), delta.y());
}
- IntPoint translated(const IntPoint& delta) const
+ Point<T> translated(const Point<T>& delta) const
{
- IntPoint point = *this;
+ Point<T> point = *this;
point.move_by(delta);
return point;
}
- IntPoint translated(int dx, int dy) const
+ Point<T> translated(T dx, T dy) const
{
- IntPoint point = *this;
+ Point<T> point = *this;
point.move_by(dx, dy);
return point;
}
- void constrain(const IntRect&);
+ Point<T> translated(T dboth) const
+ {
+ Point<T> point = *this;
+ point.move_by(dboth, dboth);
+ return point;
+ }
+
+ void constrain(const Rect<T>&);
- bool operator==(const IntPoint& other) const
+ bool operator==(const Point<T>& other) const
{
- return m_x == other.m_x
- && m_y == other.m_y;
+ return m_x == other.m_x && m_y == other.m_y;
}
- bool operator!=(const IntPoint& other) const
+ bool operator!=(const Point<T>& other) const
{
return !(*this == other);
}
- IntPoint operator-() const { return { -m_x, -m_y }; }
+ Point<T> operator+(const Point<T>& other) const { return { m_x + other.m_x, m_y + other.m_y }; }
- IntPoint operator-(const IntPoint& other) const { return { m_x - other.m_x, m_y - other.m_y }; }
- IntPoint& operator-=(const IntPoint& other)
+ Point<T>& operator+=(const Point<T>& other)
{
- m_x -= other.m_x;
- m_y -= other.m_y;
+ m_x += other.m_x;
+ m_y += other.m_y;
return *this;
}
- IntPoint& operator+=(const IntPoint& other)
+ Point<T> operator-() const { return { -m_x, -m_y }; }
+
+ Point<T> operator-(const Point<T>& other) const { return { m_x - other.m_x, m_y - other.m_y }; }
+
+ Point<T>& operator-=(const Point<T>& other)
{
- m_x += other.m_x;
- m_y += other.m_y;
+ m_x -= other.m_x;
+ m_y -= other.m_y;
return *this;
}
- IntPoint operator+(const IntPoint& other) const { return { m_x + other.m_x, m_y + other.m_y }; }
- IntPoint& operator*=(int factor)
+ Point<T> operator*(int factor) const { return { m_x * factor, m_y * factor }; }
+
+ Point<T>& operator*=(T factor)
{
m_x *= factor;
m_y *= factor;
return *this;
}
- IntPoint operator*(int factor) const { return { m_x * factor, m_y * factor }; }
- IntPoint& operator/=(int factor)
+ Point<T> operator/(int factor) const { return { m_x / factor, m_y / factor }; }
+
+ Point<T>& operator/=(int factor)
{
m_x /= factor;
m_y /= factor;
return *this;
}
- IntPoint operator/(int factor) const { return { m_x / factor, m_y / factor }; }
-
- String to_string() const;
bool is_null() const { return !m_x && !m_y; }
- int primary_offset_for_orientation(Orientation orientation) const
+ T primary_offset_for_orientation(Orientation orientation) const
{
return orientation == Orientation::Vertical ? y() : x();
}
- void set_primary_offset_for_orientation(Orientation orientation, int value)
+ void set_primary_offset_for_orientation(Orientation orientation, T value)
{
- if (orientation == Orientation::Vertical)
+ if (orientation == Orientation::Vertical) {
set_y(value);
- else
+ } else {
set_x(value);
+ }
}
- int secondary_offset_for_orientation(Orientation orientation) const
+ T secondary_offset_for_orientation(Orientation orientation) const
{
return orientation == Orientation::Vertical ? x() : y();
}
- void set_secondary_offset_for_orientation(Orientation orientation, int value)
+ void set_secondary_offset_for_orientation(Orientation orientation, T value)
{
- if (orientation == Orientation::Vertical)
+ if (orientation == Orientation::Vertical) {
set_x(value);
- else
+ } else {
set_y(value);
+ }
}
- int dx_relative_to(const IntPoint& other) const
+ T dx_relative_to(const Point<T>& other) const
{
return x() - other.x();
}
- int dy_relative_to(const IntPoint& other) const
+ T dy_relative_to(const Point<T>& other) const
{
return y() - other.y();
}
// Returns pixels moved from other in either direction
- int pixels_moved(const IntPoint& other) const
+ T pixels_moved(const Point<T>& other) const
{
return max(abs(dx_relative_to(other)), abs(dy_relative_to(other)));
}
+ float distance_from(const Point<T>& other) const
+ {
+ if (*this == other)
+ return 0;
+ return sqrtf(powf(m_x - other.m_x, 2.0f) + powf(m_y - other.m_y, 2.0f));
+ }
+
+ template<typename U>
+ Point<U> to_type() const
+ {
+ return Point<U>(*this);
+ }
+
+ String to_string() const;
+
private:
- int m_x { 0 };
- int m_y { 0 };
+ T m_x { 0 };
+ T m_y { 0 };
};
-const LogStream& operator<<(const LogStream&, const IntPoint&);
+template<typename T>
+const LogStream& operator<<(const LogStream& stream, const Point<T>& point)
+{
+ return stream << point.to_string();
+}
+
+using IntPoint = Point<int>;
+using FloatPoint = Point<float>;
}
namespace IPC {
+
bool encode(Encoder&, const Gfx::IntPoint&);
bool decode(Decoder&, Gfx::IntPoint&);
+
}
diff --git a/Libraries/LibGfx/Rect.cpp b/Libraries/LibGfx/Rect.cpp
index c654cb0d25..51ba5f509f 100644
--- a/Libraries/LibGfx/Rect.cpp
+++ b/Libraries/LibGfx/Rect.cpp
@@ -33,12 +33,13 @@
namespace Gfx {
-void IntRect::intersect(const IntRect& other)
+template<typename T>
+void Rect<T>::intersect(const Rect<T>& other)
{
- int l = max(left(), other.left());
- int r = min(right(), other.right());
- int t = max(top(), other.top());
- int b = min(bottom(), other.bottom());
+ T l = max(left(), other.left());
+ T r = min(right(), other.right());
+ T t = max(top(), other.top());
+ T b = min(bottom(), other.bottom());
if (l > r || t > b) {
m_location = {};
@@ -52,13 +53,14 @@ void IntRect::intersect(const IntRect& other)
m_size.set_height((b - t) + 1);
}
-IntRect IntRect::united(const IntRect& other) const
+template<typename T>
+Rect<T> Rect<T>::united(const Rect<T>& other) const
{
if (is_null())
return other;
if (other.is_null())
return *this;
- IntRect rect;
+ Rect<T> rect;
rect.set_left(min(left(), other.left()));
rect.set_top(min(top(), other.top()));
rect.set_right(max(right(), other.right()));
@@ -66,32 +68,33 @@ IntRect IntRect::united(const IntRect& other) const
return rect;
}
-Vector<IntRect, 4> IntRect::shatter(const IntRect& hammer) const
+template<typename T>
+Vector<Rect<T>, 4> Rect<T>::shatter(const Rect<T>& hammer) const
{
- Vector<IntRect, 4> pieces;
+ Vector<Rect<T>, 4> pieces;
if (!intersects(hammer)) {
pieces.unchecked_append(*this);
return pieces;
}
- IntRect top_shard {
+ Rect<T> top_shard {
x(),
y(),
width(),
hammer.y() - y()
};
- IntRect bottom_shard {
+ Rect<T> bottom_shard {
x(),
hammer.y() + hammer.height(),
width(),
(y() + height()) - (hammer.y() + hammer.height())
};
- IntRect left_shard {
+ Rect<T> left_shard {
x(),
max(hammer.y(), y()),
hammer.x() - x(),
min((hammer.y() + hammer.height()), (y() + height())) - max(hammer.y(), y())
};
- IntRect right_shard {
+ Rect<T> right_shard {
hammer.x() + hammer.width(),
max(hammer.y(), y()),
right() - hammer.right(),
@@ -109,7 +112,8 @@ Vector<IntRect, 4> IntRect::shatter(const IntRect& hammer) const
return pieces;
}
-void IntRect::align_within(const IntRect& other, TextAlignment alignment)
+template<typename T>
+void Rect<T>::align_within(const Rect<T>& other, TextAlignment alignment)
{
switch (alignment) {
case TextAlignment::Center:
@@ -133,14 +137,16 @@ void IntRect::align_within(const IntRect& other, TextAlignment alignment)
}
}
+template<>
String IntRect::to_string() const
{
return String::format("[%d,%d %dx%d]", x(), y(), width(), height());
}
-const LogStream& operator<<(const LogStream& stream, const IntRect& value)
+template<>
+String FloatRect::to_string() const
{
- return stream << value.to_string();
+ return String::format("[%f,%f %fx%f]", x(), y(), width(), height());
}
}
@@ -166,3 +172,6 @@ bool decode(Decoder& decoder, Gfx::IntRect& rect)
}
}
+
+template class Gfx::Rect<int>;
+template class Gfx::Rect<float>;
diff --git a/Libraries/LibGfx/Rect.h b/Libraries/LibGfx/Rect.h
index 67c495b193..94d133d846 100644
--- a/Libraries/LibGfx/Rect.h
+++ b/Libraries/LibGfx/Rect.h
@@ -26,30 +26,58 @@
#pragma once
-#include <AK/Forward.h>
#include <LibGfx/Orientation.h>
#include <LibGfx/Point.h>
#include <LibGfx/Size.h>
#include <LibGfx/TextAlignment.h>
-#include <LibIPC/Forward.h>
-#include <stdlib.h>
+#include <LibM/math.h>
namespace Gfx {
-class IntRect {
+template<typename T>
+T abst(T value)
+{
+ return value < 0 ? -value : value;
+}
+
+template<typename T>
+class Rect {
public:
- IntRect() {}
- IntRect(int x, int y, int width, int height)
+ Rect() {}
+
+ Rect(T x, T y, T width, T height)
+ : m_location(x, y)
+ , m_size(width, height)
+ {
+ }
+
+ template<typename U>
+ Rect(U x, U y, U width, U height)
: m_location(x, y)
, m_size(width, height)
{
}
- IntRect(const IntPoint& location, const IntSize& size)
+
+ Rect(const Point<T>& location, const Size<T>& size)
+ : m_location(location)
+ , m_size(size)
+ {
+ }
+
+ template<typename U>
+ Rect(const Point<U>& location, const Size<U>& size)
: m_location(location)
, m_size(size)
{
}
+ template<typename U>
+ explicit Rect(const Rect<U>& other)
+ : m_location(other.location())
+ , m_size(other.size())
+ {
+ }
+
bool is_null() const
{
return width() == 0 && height() == 0;
@@ -60,38 +88,38 @@ public:
return width() <= 0 || height() <= 0;
}
- void move_by(int dx, int dy)
+ void move_by(T dx, T dy)
{
m_location.move_by(dx, dy);
}
- void move_by(const IntPoint& delta)
+ void move_by(const Point<T>& delta)
{
m_location.move_by(delta);
}
- IntPoint center() const
+ Point<T> center() const
{
return { x() + width() / 2, y() + height() / 2 };
}
- void set_location(const IntPoint& location)
+ void set_location(const Point<T>& location)
{
m_location = location;
}
- void set_size(const IntSize& size)
+ void set_size(const Size<T>& size)
{
m_size = size;
}
- void set_size(int width, int height)
+ void set_size(T width, T height)
{
m_size.set_width(width);
m_size.set_height(height);
}
- void inflate(int w, int h)
+ void inflate(T w, T h)
{
set_x(x() - w / 2);
set_width(width() + w);
@@ -99,7 +127,7 @@ public:
set_height(height() + h);
}
- void shrink(int w, int h)
+ void shrink(T w, T h)
{
set_x(x() + w / 2);
set_width(width() - w);
@@ -107,55 +135,55 @@ public:
set_height(height() - h);
}
- IntRect shrunken(int w, int h) const
+ Rect<T> shrunken(T w, T h) const
{
- IntRect rect = *this;
+ Rect<T> rect = *this;
rect.shrink(w, h);
return rect;
}
- IntRect inflated(int w, int h) const
+ Rect<T> inflated(T w, T h) const
{
- IntRect rect = *this;
+ Rect<T> rect = *this;
rect.inflate(w, h);
return rect;
}
- IntRect translated(int dx, int dy) const
+ Rect<T> translated(T dx, T dy) const
{
- IntRect rect = *this;
+ Rect<T> rect = *this;
rect.move_by(dx, dy);
return rect;
}
- IntRect translated(const IntPoint& delta) const
+ Rect<T> translated(const Point<T>& delta) const
{
- IntRect rect = *this;
+ Rect<T> rect = *this;
rect.move_by(delta);
return rect;
}
- bool contains_vertically(int y) const
+ bool contains_vertically(T y) const
{
return y >= top() && y <= bottom();
}
- bool contains_horizontally(int x) const
+ bool contains_horizontally(T x) const
{
return x >= left() && x <= right();
}
- bool contains(int x, int y) const
+ bool contains(T x, T y) const
{
return x >= m_location.x() && x <= right() && y >= m_location.y() && y <= bottom();
}
- bool contains(const IntPoint& point) const
+ bool contains(const Point<T>& point) const
{
return contains(point.x(), point.y());
}
- bool contains(const IntRect& other) const
+ bool contains(const Rect<T>& other) const
{
return left() <= other.left()
&& right() >= other.right()
@@ -173,70 +201,68 @@ public:
void set_primary_size_for_orientation(Orientation orientation, int value) { m_size.set_primary_size_for_orientation(orientation, value); }
void set_secondary_size_for_orientation(Orientation orientation, int value) { m_size.set_secondary_size_for_orientation(orientation, value); }
- int first_edge_for_orientation(Orientation orientation) const
+ T first_edge_for_orientation(Orientation orientation) const
{
if (orientation == Orientation::Vertical)
return top();
return left();
}
- int last_edge_for_orientation(Orientation orientation) const
+ T last_edge_for_orientation(Orientation orientation) const
{
if (orientation == Orientation::Vertical)
return bottom();
return right();
}
- int left() const { return x(); }
- int right() const { return x() + width() - 1; }
- int top() const { return y(); }
- int bottom() const { return y() + height() - 1; }
+ T left() const { return x(); }
+ T right() const { return x() + width() - 1; }
+ T top() const { return y(); }
+ T bottom() const { return y() + height() - 1; }
- void set_left(int left)
+ void set_left(T left)
{
set_x(left);
}
- void set_top(int top)
+ void set_top(T top)
{
set_y(top);
}
- void set_right(int right)
+ void set_right(T right)
{
set_width(right - x() + 1);
}
- void set_bottom(int bottom)
+ void set_bottom(T bottom)
{
set_height(bottom - y() + 1);
}
- void set_right_without_resize(int new_right)
+ void set_right_without_resize(T new_right)
{
int delta = new_right - right();
move_by(delta, 0);
}
- void set_bottom_without_resize(int new_bottom)
+ void set_bottom_without_resize(T new_bottom)
{
int delta = new_bottom - bottom();
move_by(0, delta);
}
- bool intersects_vertically(const IntRect& other) const
+ bool intersects_vertically(const Rect<T>& other) const
{
- return top() <= other.bottom()
- && other.top() <= bottom();
+ return top() <= other.bottom() && other.top() <= bottom();
}
- bool intersects_horizontally(const IntRect& other) const
+ bool intersects_horizontally(const Rect<T>& other) const
{
- return left() <= other.right()
- && other.left() <= right();
+ return left() <= other.right() && other.left() <= right();
}
- bool intersects(const IntRect& other) const
+ bool intersects(const Rect<T>& other) const
{
return left() <= other.right()
&& other.left() <= right()
@@ -244,100 +270,112 @@ public:
&& other.top() <= bottom();
}
- int x() const { return location().x(); }
- int y() const { return location().y(); }
- int width() const { return m_size.width(); }
- int height() const { return m_size.height(); }
+ T x() const { return location().x(); }
+ T y() const { return location().y(); }
+ T width() const { return m_size.width(); }
+ T height() const { return m_size.height(); }
- void set_x(int x) { m_location.set_x(x); }
- void set_y(int y) { m_location.set_y(y); }
- void set_width(int width) { m_size.set_width(width); }
- void set_height(int height) { m_size.set_height(height); }
+ void set_x(T x) { m_location.set_x(x); }
+ void set_y(T y) { m_location.set_y(y); }
+ void set_width(T width) { m_size.set_width(width); }
+ void set_height(T height) { m_size.set_height(height); }
- IntPoint location() const { return m_location; }
- IntSize size() const { return m_size; }
+ const Point<T>& location() const { return m_location; }
+ const Size<T>& size() const { return m_size; }
- Vector<IntRect, 4> shatter(const IntRect& hammer) const;
+ Vector<Rect<T>, 4> shatter(const Rect<T>& hammer) const;
- bool operator==(const IntRect& other) const
+ bool operator==(const Rect<T>& other) const
{
- return m_location == other.m_location
- && m_size == other.m_size;
+ return m_location == other.m_location && m_size == other.m_size;
}
- bool operator!=(const IntRect& other) const
+ bool operator!=(const Rect<T>& other) const
{
return !(*this == other);
}
- void intersect(const IntRect&);
+ void intersect(const Rect<T>&);
- static IntRect from_two_points(const IntPoint& a, const IntPoint& b)
+ static Rect<T> from_two_points(const Point<T>& a, const Point<T>& b)
{
- return { min(a.x(), b.x()), min(a.y(), b.y()), abs(a.x() - b.x()), abs(a.y() - b.y()) };
+ return { min(a.x(), b.x()), min(a.y(), b.y()), abst(a.x() - b.x()), abst(a.y() - b.y()) };
}
- static IntRect intersection(const IntRect& a, const IntRect& b)
+ static Rect<T> intersection(const Rect<T>& a, const Rect<T>& b)
{
- IntRect r(a);
+ Rect<T> r = a;
r.intersect(b);
return r;
}
- IntRect intersected(const IntRect& other) const
+ Rect<T> intersected(const Rect<T>& other) const
{
return intersection(*this, other);
}
- IntRect united(const IntRect&) const;
+ Rect<T> united(const Rect<T>&) const;
- IntPoint top_left() const { return { left(), top() }; }
- IntPoint top_right() const { return { right(), top() }; }
- IntPoint bottom_left() const { return { left(), bottom() }; }
- IntPoint bottom_right() const { return { right(), bottom() }; }
+ Point<T> top_left() const { return { left(), top() }; }
+ Point<T> top_right() const { return { right(), top() }; }
+ Point<T> bottom_left() const { return { left(), bottom() }; }
+ Point<T> bottom_right() const { return { right(), bottom() }; }
- void align_within(const IntRect&, TextAlignment);
+ void align_within(const Rect<T>&, TextAlignment);
- void center_within(const IntRect& other)
+ void center_within(const Rect<T>& other)
{
center_horizontally_within(other);
center_vertically_within(other);
}
- void center_horizontally_within(const IntRect& other)
+ void center_horizontally_within(const Rect<T>& other)
{
set_x(other.center().x() - width() / 2);
}
- void center_vertically_within(const IntRect& other)
+ void center_vertically_within(const Rect<T>& other)
{
set_y(other.center().y() - height() / 2);
}
+ template<typename U>
+ Rect<U> to() const
+ {
+ return Rect<U>(*this);
+ }
+
String to_string() const;
private:
- IntPoint m_location;
- IntSize m_size;
+ Point<T> m_location;
+ Size<T> m_size;
};
-inline void IntPoint::constrain(const IntRect& rect)
+template<typename T>
+const LogStream& operator<<(const LogStream& stream, const Rect<T>& rect)
{
- if (x() < rect.left())
- set_x(rect.left());
- else if (x() > rect.right())
- set_x(rect.right());
- if (y() < rect.top())
- set_y(rect.top());
- else if (y() > rect.bottom())
- set_y(rect.bottom());
+ return stream << rect.to_string();
}
-const LogStream& operator<<(const LogStream&, const IntRect&);
+using IntRect = Rect<int>;
+using FloatRect = Rect<float>;
+
+ALWAYS_INLINE IntRect enclosing_int_rect(const FloatRect& float_rect)
+{
+ return {
+ (int)float_rect.x(),
+ (int)float_rect.y(),
+ (int)ceilf(float_rect.width()),
+ (int)ceilf(float_rect.height()),
+ };
+}
}
namespace IPC {
+
bool decode(Decoder&, Gfx::IntRect&);
bool encode(Encoder&, const Gfx::IntRect&);
+
}
diff --git a/Libraries/LibGfx/ShareableBitmap.cpp b/Libraries/LibGfx/ShareableBitmap.cpp
index ea19a5c67f..662a294f25 100644
--- a/Libraries/LibGfx/ShareableBitmap.cpp
+++ b/Libraries/LibGfx/ShareableBitmap.cpp
@@ -27,6 +27,7 @@
#include <AK/SharedBuffer.h>
#include <LibGfx/Bitmap.h>
#include <LibGfx/ShareableBitmap.h>
+#include <LibGfx/Size.h>
#include <LibIPC/Decoder.h>
#include <LibIPC/Encoder.h>
diff --git a/Libraries/LibGfx/ShareableBitmap.h b/Libraries/LibGfx/ShareableBitmap.h
index ac0ecca36b..443835f605 100644
--- a/Libraries/LibGfx/ShareableBitmap.h
+++ b/Libraries/LibGfx/ShareableBitmap.h
@@ -57,6 +57,8 @@ private:
}
namespace IPC {
+
bool encode(Encoder&, const Gfx::ShareableBitmap&);
bool decode(Decoder&, Gfx::ShareableBitmap&);
+
}
diff --git a/Libraries/LibGfx/Size.cpp b/Libraries/LibGfx/Size.cpp
index 648aa5708b..c2d809c357 100644
--- a/Libraries/LibGfx/Size.cpp
+++ b/Libraries/LibGfx/Size.cpp
@@ -31,14 +31,16 @@
namespace Gfx {
+template<>
String IntSize::to_string() const
{
return String::format("[%dx%d]", m_width, m_height);
}
-const LogStream& operator<<(const LogStream& stream, const IntSize& value)
+template<>
+String FloatSize::to_string() const
{
- return stream << value.to_string();
+ return String::format("[%fx%f]", m_width, m_height);
}
}
@@ -64,3 +66,6 @@ bool decode(Decoder& decoder, Gfx::IntSize& size)
}
}
+
+template class Gfx::Size<int>;
+template class Gfx::Size<float>;
diff --git a/Libraries/LibGfx/Size.h b/Libraries/LibGfx/Size.h
index 59eb27a66d..05b71a246b 100644
--- a/Libraries/LibGfx/Size.h
+++ b/Libraries/LibGfx/Size.h
@@ -32,88 +32,121 @@
namespace Gfx {
-class IntSize {
+template<typename T>
+class Size {
public:
- IntSize() {}
- IntSize(int w, int h)
+ Size() {}
+
+ Size(T w, T h)
: m_width(w)
, m_height(h)
{
}
+ template<typename U>
+ Size(U width, U height)
+ : m_width(width)
+ , m_height(height)
+ {
+ }
+
+ template<typename U>
+ explicit Size(const Size<U>& other)
+ : m_width(other.width())
+ , m_height(other.height())
+ {
+ }
+
bool is_null() const { return !m_width && !m_height; }
bool is_empty() const { return m_width <= 0 || m_height <= 0; }
- int width() const { return m_width; }
- int height() const { return m_height; }
+ T width() const { return m_width; }
+ T height() const { return m_height; }
- int area() const { return width() * height(); }
+ T area() const { return width() * height(); }
- void set_width(int w) { m_width = w; }
- void set_height(int h) { m_height = h; }
+ void set_width(T w) { m_width = w; }
+ void set_height(T h) { m_height = h; }
- bool operator==(const IntSize& other) const
+ bool operator==(const Size<T>& other) const
{
return m_width == other.m_width && m_height == other.m_height;
}
- bool operator!=(const IntSize& other) const
+ bool operator!=(const Size<T>& other) const
{
return !(*this == other);
}
- IntSize& operator-=(const IntSize& other)
+ Size<T>& operator-=(const Size<T>& other)
{
m_width -= other.m_width;
m_height -= other.m_height;
return *this;
}
- IntSize& operator+=(const IntSize& other)
+ Size<T>& operator+=(const Size<T>& other)
{
m_width += other.m_width;
m_height += other.m_height;
return *this;
}
- int primary_size_for_orientation(Orientation orientation) const
+ T primary_size_for_orientation(Orientation orientation) const
{
return orientation == Orientation::Vertical ? height() : width();
}
- void set_primary_size_for_orientation(Orientation orientation, int value)
+ void set_primary_size_for_orientation(Orientation orientation, T value)
{
- if (orientation == Orientation::Vertical)
+ if (orientation == Orientation::Vertical) {
set_height(value);
- else
+ } else {
set_width(value);
+ }
}
- int secondary_size_for_orientation(Orientation orientation) const
+ T secondary_size_for_orientation(Orientation orientation) const
{
return orientation == Orientation::Vertical ? width() : height();
}
- void set_secondary_size_for_orientation(Orientation orientation, int value)
+ void set_secondary_size_for_orientation(Orientation orientation, T value)
{
- if (orientation == Orientation::Vertical)
+ if (orientation == Orientation::Vertical) {
set_width(value);
- else
+ } else {
set_height(value);
+ }
+ }
+
+ template<typename U>
+ Size<U> to_type() const
+ {
+ return Size<U>(*this);
}
String to_string() const;
private:
- int m_width { 0 };
- int m_height { 0 };
+ T m_width { 0 };
+ T m_height { 0 };
};
-const LogStream& operator<<(const LogStream&, const IntSize&);
+template<typename T>
+const LogStream& operator<<(const LogStream& stream, const Gfx::Size<T>& size)
+{
+ return stream << size.to_string();
+}
+
+using IntSize = Size<int>;
+using FloatSize = Size<float>;
}
namespace IPC {
+
bool encode(Encoder&, const Gfx::IntSize&);
bool decode(Decoder&, Gfx::IntSize&);
+
}