diff options
author | Matthew Olsson <matthewcolsson@gmail.com> | 2020-07-25 21:31:47 -0700 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-07-27 01:06:26 +0200 |
commit | 335916d8db8421565c4cc232b36a397d6a7fb864 (patch) | |
tree | cbc8215d0f07d1eb014f0b2287d3d4f5aa16419c /Libraries/LibGfx | |
parent | 7a1c328417972efc33af8bc7cbc745340369a8f0 (diff) | |
download | serenity-335916d8db8421565c4cc232b36a397d6a7fb864.zip |
LibGfx: Templatize Point, Size, and Rect
Diffstat (limited to 'Libraries/LibGfx')
-rw-r--r-- | Libraries/LibGfx/AffineTransform.cpp | 23 | ||||
-rw-r--r-- | Libraries/LibGfx/AffineTransform.h | 12 | ||||
-rw-r--r-- | Libraries/LibGfx/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Libraries/LibGfx/FloatRect.cpp | 135 | ||||
-rw-r--r-- | Libraries/LibGfx/FloatRect.h | 335 | ||||
-rw-r--r-- | Libraries/LibGfx/FloatSize.h | 125 | ||||
-rw-r--r-- | Libraries/LibGfx/Forward.h | 24 | ||||
-rw-r--r-- | Libraries/LibGfx/Painter.cpp | 7 | ||||
-rw-r--r-- | Libraries/LibGfx/Path.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibGfx/Path.h | 3 | ||||
-rw-r--r-- | Libraries/LibGfx/Point.cpp | 27 | ||||
-rw-r--r-- | Libraries/LibGfx/Point.h | 149 | ||||
-rw-r--r-- | Libraries/LibGfx/Rect.cpp | 41 | ||||
-rw-r--r-- | Libraries/LibGfx/Rect.h | 216 | ||||
-rw-r--r-- | Libraries/LibGfx/ShareableBitmap.cpp | 1 | ||||
-rw-r--r-- | Libraries/LibGfx/ShareableBitmap.h | 2 | ||||
-rw-r--r-- | Libraries/LibGfx/Size.cpp | 9 | ||||
-rw-r--r-- | Libraries/LibGfx/Size.h | 79 |
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&); + } |