diff options
author | Andreas Kling <kling@serenityos.org> | 2020-04-16 21:03:17 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-04-16 21:04:46 +0200 |
commit | 60c2e41079c94ed30c53f8c1ba167d24247aa875 (patch) | |
tree | 87cdbb96947fe6d303b02286f5f09a8a1e67997e | |
parent | 72df9c741746a16125a46b6e2be567c45925911e (diff) | |
download | serenity-60c2e41079c94ed30c53f8c1ba167d24247aa875.zip |
LibGfx: Add Gfx::Path, a basic 2D path with <canvas> semantics
This will be used to implement painting of 2D paths. This first patch
adds support for line_to(), move_to() and close().
It will try to have the same semantics as the HTML <canvas> element.
To stroke a Path, simply pass it to Painter::stroke_path().
-rw-r--r-- | Libraries/LibGfx/Forward.h | 1 | ||||
-rw-r--r-- | Libraries/LibGfx/Makefile | 1 | ||||
-rw-r--r-- | Libraries/LibGfx/Painter.cpp | 21 | ||||
-rw-r--r-- | Libraries/LibGfx/Painter.h | 2 | ||||
-rw-r--r-- | Libraries/LibGfx/Path.cpp | 76 | ||||
-rw-r--r-- | Libraries/LibGfx/Path.h | 75 |
6 files changed, 176 insertions, 0 deletions
diff --git a/Libraries/LibGfx/Forward.h b/Libraries/LibGfx/Forward.h index 37946b3b43..6a6378c9b2 100644 --- a/Libraries/LibGfx/Forward.h +++ b/Libraries/LibGfx/Forward.h @@ -42,6 +42,7 @@ class ImageDecoder; class Painter; class Palette; class PaletteImpl; +class Path; class Point; class Rect; class ShareableBitmap; diff --git a/Libraries/LibGfx/Makefile b/Libraries/LibGfx/Makefile index 2645693cee..201338c401 100644 --- a/Libraries/LibGfx/Makefile +++ b/Libraries/LibGfx/Makefile @@ -11,6 +11,7 @@ OBJS = \ PNGLoader.o \ Painter.o \ Palette.o \ + Path.o \ Point.o \ Rect.o \ ShareableBitmap.o \ diff --git a/Libraries/LibGfx/Painter.cpp b/Libraries/LibGfx/Painter.cpp index 2033f0fac7..a9b5730778 100644 --- a/Libraries/LibGfx/Painter.cpp +++ b/Libraries/LibGfx/Painter.cpp @@ -35,6 +35,7 @@ #include <AK/StringBuilder.h> #include <AK/Utf8View.h> #include <LibGfx/CharacterBitmap.h> +#include <LibGfx/Path.h> #include <math.h> #include <stdio.h> #include <unistd.h> @@ -1010,4 +1011,24 @@ PainterStateSaver::~PainterStateSaver() m_painter.restore(); } +void Painter::stroke_path(const Path& path, Color color, int thickness) +{ + FloatPoint cursor; + + for (auto& segment : path.segments()) { + switch (segment.type) { + case Path::Segment::Type::Invalid: + ASSERT_NOT_REACHED(); + break; + case Path::Segment::Type::MoveTo: + cursor = segment.point; + break; + case Path::Segment::Type::LineTo: + draw_line(Point(cursor.x(), cursor.y()), Point(segment.point.x(), segment.point.y()), color, thickness); + cursor = segment.point; + break; + } + } +} + } diff --git a/Libraries/LibGfx/Painter.h b/Libraries/LibGfx/Painter.h index b4923bded1..61b974a559 100644 --- a/Libraries/LibGfx/Painter.h +++ b/Libraries/LibGfx/Painter.h @@ -69,6 +69,8 @@ public: void draw_emoji(const Point&, const Gfx::Bitmap&, const Font&); void draw_glyph_or_emoji(const Point&, u32 codepoint, const Font&, Color); + void stroke_path(const Path&, Color, int thickness); + const Font& font() const { return *state().font; } void set_font(const Font& font) { state().font = &font; } diff --git a/Libraries/LibGfx/Path.cpp b/Libraries/LibGfx/Path.cpp new file mode 100644 index 0000000000..cd7e3dfcb8 --- /dev/null +++ b/Libraries/LibGfx/Path.cpp @@ -0,0 +1,76 @@ +/* + * 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. + */ + +#include <AK/StringBuilder.h> +#include <LibGfx/Path.h> + +namespace Gfx { + +void Path::close() +{ + if (m_segments.size() <= 1) + return; + + auto& last_point = m_segments.last().point; + + for (ssize_t i = m_segments.size() - 1; i >= 0; --i) { + auto& segment = m_segments[i]; + if (segment.type == Segment::Type::MoveTo) { + if (last_point == segment.point) + return; + m_segments.append({ Segment::Type::LineTo, segment.point }); + return; + } + } +} + +String Path::to_string() const +{ + StringBuilder builder; + builder.append("Path { "); + for (auto& segment : m_segments) { + switch (segment.type) { + case Segment::Type::MoveTo: + builder.append("MoveTo"); + break; + case Segment::Type::LineTo: + builder.append("LineTo"); + break; + case Segment::Type::Invalid: + builder.append("Invalid"); + break; + } + builder.append('('); + builder.append(segment.point.to_string()); + builder.append(')'); + + builder.append(' '); + } + builder.append("}"); + return builder.to_string(); +} + +} diff --git a/Libraries/LibGfx/Path.h b/Libraries/LibGfx/Path.h new file mode 100644 index 0000000000..2d9c74495c --- /dev/null +++ b/Libraries/LibGfx/Path.h @@ -0,0 +1,75 @@ +/* + * 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. + */ + +#pragma once + +#include <AK/Vector.h> +#include <LibGfx/FloatPoint.h> +#include <LibGfx/Forward.h> + +namespace Gfx { + +class Path { +public: + struct Segment { + enum class Type { + Invalid, + MoveTo, + LineTo, + }; + + Type type { Type::Invalid }; + FloatPoint point; + }; + + Path() {} + + void move_to(const FloatPoint& point) + { + m_segments.append({ Segment::Type::MoveTo, point }); + } + + void line_to(const FloatPoint& point) + { + m_segments.append({ Segment::Type::LineTo, point }); + } + + void close(); + + const Vector<Segment>& segments() const { return m_segments; } + + String to_string() const; + +private: + Vector<Segment> m_segments; +}; + +inline const LogStream& operator<<(const LogStream& stream, const Path& path) +{ + return stream << path.to_string(); +} + +} |