diff options
author | Andreas Kling <kling@serenityos.org> | 2020-02-06 12:04:00 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-02-06 12:04:00 +0100 |
commit | 9ac94d393e02c8e725d58affd03b1fd0e0c45552 (patch) | |
tree | 7152a9134e30bf1b965c6e8f9e5b8f71098da861 /Libraries/LibDraw | |
parent | 11580babbfb1b8ae0acab2400f11d905c35642f5 (diff) | |
download | serenity-9ac94d393e02c8e725d58affd03b1fd0e0c45552.zip |
LibGfx: Rename from LibDraw :^)
Diffstat (limited to 'Libraries/LibDraw')
38 files changed, 0 insertions, 6292 deletions
diff --git a/Libraries/LibDraw/CharacterBitmap.cpp b/Libraries/LibDraw/CharacterBitmap.cpp deleted file mode 100644 index d51ff1d080..0000000000 --- a/Libraries/LibDraw/CharacterBitmap.cpp +++ /dev/null @@ -1,46 +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. - */ - -#include "CharacterBitmap.h" - -namespace Gfx { - -CharacterBitmap::CharacterBitmap(const char* ascii_data, unsigned width, unsigned height) - : m_bits(ascii_data) - , m_size(width, height) -{ -} - -CharacterBitmap::~CharacterBitmap() -{ -} - -NonnullRefPtr<CharacterBitmap> CharacterBitmap::create_from_ascii(const char* asciiData, unsigned width, unsigned height) -{ - return adopt(*new CharacterBitmap(asciiData, width, height)); -} - -} diff --git a/Libraries/LibDraw/CharacterBitmap.h b/Libraries/LibDraw/CharacterBitmap.h deleted file mode 100644 index 0a77d123af..0000000000 --- a/Libraries/LibDraw/CharacterBitmap.h +++ /dev/null @@ -1,54 +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 "Size.h" -#include <AK/RefCounted.h> -#include <AK/RefPtr.h> - -namespace Gfx { - -class CharacterBitmap : public RefCounted<CharacterBitmap> { -public: - static NonnullRefPtr<CharacterBitmap> create_from_ascii(const char* asciiData, unsigned width, unsigned height); - ~CharacterBitmap(); - - bool bit_at(unsigned x, unsigned y) const { return m_bits[y * width() + x] == '#'; } - const char* bits() const { return m_bits; } - - Size size() const { return m_size; } - unsigned width() const { return m_size.width(); } - unsigned height() const { return m_size.height(); } - -private: - CharacterBitmap(const char* b, unsigned w, unsigned h); - - const char* m_bits { nullptr }; - Size m_size; -}; - -} diff --git a/Libraries/LibDraw/Color.cpp b/Libraries/LibDraw/Color.cpp deleted file mode 100644 index dcfdf90e80..0000000000 --- a/Libraries/LibDraw/Color.cpp +++ /dev/null @@ -1,340 +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. - */ - -#include <AK/Assertions.h> -#include <LibDraw/Color.h> -#include <LibDraw/SystemTheme.h> -#include <ctype.h> -#include <stdio.h> - -Color::Color(NamedColor named) -{ - struct { - u8 r; - u8 g; - u8 b; - } rgb; - - switch (named) { - case Black: - rgb = { 0, 0, 0 }; - break; - case White: - rgb = { 255, 255, 255 }; - break; - case Red: - rgb = { 255, 0, 0 }; - break; - case Green: - rgb = { 0, 255, 0 }; - break; - case Cyan: - rgb = { 0, 255, 255 }; - break; - case DarkCyan: - rgb = { 0, 127, 127 }; - break; - case MidCyan: - rgb = { 0, 192, 192 }; - break; - case Blue: - rgb = { 0, 0, 255 }; - break; - case Yellow: - rgb = { 255, 255, 0 }; - break; - case Magenta: - rgb = { 255, 0, 255 }; - break; - case DarkGray: - rgb = { 64, 64, 64 }; - break; - case MidGray: - rgb = { 127, 127, 127 }; - break; - case LightGray: - rgb = { 192, 192, 192 }; - break; - case MidGreen: - rgb = { 0, 192, 0 }; - break; - case MidBlue: - rgb = { 0, 0, 192 }; - break; - case MidRed: - rgb = { 192, 0, 0 }; - break; - case MidMagenta: - rgb = { 192, 0, 192 }; - break; - case DarkGreen: - rgb = { 0, 128, 0 }; - break; - case DarkBlue: - rgb = { 0, 0, 128 }; - break; - case DarkRed: - rgb = { 128, 0, 0 }; - break; - case WarmGray: - rgb = { 212, 208, 200 }; - break; - default: - ASSERT_NOT_REACHED(); - break; - } - - m_value = 0xff000000 | (rgb.r << 16) | (rgb.g << 8) | rgb.b; -} - -String Color::to_string() const -{ - return String::format("#%b%b%b%b", red(), green(), blue(), alpha()); -} - -Optional<Color> Color::from_string(const StringView& string) -{ - if (string.is_empty()) - return {}; - - struct ColorAndWebName { - RGBA32 color; - const char* name; - }; - - const ColorAndWebName web_colors[] = { - // CSS Level 1 - { 0x000000, "black" }, - { 0xc0c0c0, "silver" }, - { 0x808080, "gray" }, - { 0xffffff, "white" }, - { 0x800000, "maroon" }, - { 0xff0000, "red" }, - { 0x800080, "purple" }, - { 0xff00ff, "fuchsia" }, - { 0x008000, "green" }, - { 0x00ff00, "lime" }, - { 0x808000, "olive" }, - { 0xffff00, "yellow" }, - { 0x000080, "navy" }, - { 0x0000ff, "blue" }, - { 0x008080, "teal" }, - { 0x00ffff, "aqua" }, - // CSS Level 2 (Revision 1) - { 0xffa500, "orange" }, - // CSS Color Module Level 3 - { 0xf0f8ff, "aliceblue" }, - { 0xfaebd7, "antiquewhite" }, - { 0x7fffd4, "aquamarine" }, - { 0xf0ffff, "azure" }, - { 0xf5f5dc, "beige" }, - { 0xffe4c4, "bisque" }, - { 0xffebcd, "blanchedalmond" }, - { 0x8a2be2, "blueviolet" }, - { 0xa52a2a, "brown" }, - { 0xdeb887, "burlywood" }, - { 0x5f9ea0, "cadetblue" }, - { 0x7fff00, "chartreuse" }, - { 0xd2691e, "chocolate" }, - { 0xff7f50, "coral" }, - { 0x6495ed, "cornflowerblue" }, - { 0xfff8dc, "cornsilk" }, - { 0xdc143c, "crimson" }, - { 0x00ffff, "cyan" }, - { 0x00008b, "darkblue" }, - { 0x008b8b, "darkcyan" }, - { 0xb8860b, "darkgoldenrod" }, - { 0xa9a9a9, "darkgray" }, - { 0x006400, "darkgreen" }, - { 0xa9a9a9, "darkgrey" }, - { 0xbdb76b, "darkkhaki" }, - { 0x8b008b, "darkmagenta" }, - { 0x556b2f, "darkolivegreen" }, - { 0xff8c00, "darkorange" }, - { 0x9932cc, "darkorchid" }, - { 0x8b0000, "darkred" }, - { 0xe9967a, "darksalmon" }, - { 0x8fbc8f, "darkseagreen" }, - { 0x483d8b, "darkslateblue" }, - { 0x2f4f4f, "darkslategray" }, - { 0x2f4f4f, "darkslategrey" }, - { 0x00ced1, "darkturquoise" }, - { 0x9400d3, "darkviolet" }, - { 0xff1493, "deeppink" }, - { 0x00bfff, "deepskyblue" }, - { 0x696969, "dimgray" }, - { 0x696969, "dimgrey" }, - { 0x1e90ff, "dodgerblue" }, - { 0xb22222, "firebrick" }, - { 0xfffaf0, "floralwhite" }, - { 0x228b22, "forestgreen" }, - { 0xdcdcdc, "gainsboro" }, - { 0xf8f8ff, "ghostwhite" }, - { 0xffd700, "gold" }, - { 0xdaa520, "goldenrod" }, - { 0xadff2f, "greenyellow" }, - { 0x808080, "grey" }, - { 0xf0fff0, "honeydew" }, - { 0xff69b4, "hotpink" }, - { 0xcd5c5c, "indianred" }, - { 0x4b0082, "indigo" }, - { 0xfffff0, "ivory" }, - { 0xf0e68c, "khaki" }, - { 0xe6e6fa, "lavender" }, - { 0xfff0f5, "lavenderblush" }, - { 0x7cfc00, "lawngreen" }, - { 0xfffacd, "lemonchiffon" }, - { 0xadd8e6, "lightblue" }, - { 0xf08080, "lightcoral" }, - { 0xe0ffff, "lightcyan" }, - { 0xfafad2, "lightgoldenrody" }, - { 0xd3d3d3, "lightgray" }, - { 0x90ee90, "lightgreen" }, - { 0xd3d3d3, "lightgrey" }, - { 0xffb6c1, "lightpink" }, - { 0xffa07a, "lightsalmon" }, - { 0x20b2aa, "lightseagreen" }, - { 0x87cefa, "lightskyblue" }, - { 0x778899, "lightslategray" }, - { 0x778899, "lightslategrey" }, - { 0xb0c4de, "lightsteelblue" }, - { 0xffffe0, "lightyellow" }, - { 0x32cd32, "limegreen" }, - { 0xfaf0e6, "linen" }, - { 0xff00ff, "magenta" }, - { 0x66cdaa, "mediumaquamarin" }, - { 0x0000cd, "mediumblue" }, - { 0xba55d3, "mediumorchid" }, - { 0x9370db, "mediumpurple" }, - { 0x3cb371, "mediumseagreen" }, - { 0x7b68ee, "mediumslateblue" }, - { 0x00fa9a, "mediumspringgre" }, - { 0x48d1cc, "mediumturquoise" }, - { 0xc71585, "mediumvioletred" }, - { 0x191970, "midnightblue" }, - { 0xf5fffa, "mintcream" }, - { 0xffe4e1, "mistyrose" }, - { 0xffe4b5, "moccasin" }, - { 0xffdead, "navajowhite" }, - { 0xfdf5e6, "oldlace" }, - { 0x6b8e23, "olivedrab" }, - { 0xff4500, "orangered" }, - { 0xda70d6, "orchid" }, - { 0xeee8aa, "palegoldenrod" }, - { 0x98fb98, "palegreen" }, - { 0xafeeee, "paleturquoise" }, - { 0xdb7093, "palevioletred" }, - { 0xffefd5, "papayawhip" }, - { 0xffdab9, "peachpuff" }, - { 0xcd853f, "peru" }, - { 0xffc0cb, "pink" }, - { 0xdda0dd, "plum" }, - { 0xb0e0e6, "powderblue" }, - { 0xbc8f8f, "rosybrown" }, - { 0x4169e1, "royalblue" }, - { 0x8b4513, "saddlebrown" }, - { 0xfa8072, "salmon" }, - { 0xf4a460, "sandybrown" }, - { 0x2e8b57, "seagreen" }, - { 0xfff5ee, "seashell" }, - { 0xa0522d, "sienna" }, - { 0x87ceeb, "skyblue" }, - { 0x6a5acd, "slateblue" }, - { 0x708090, "slategray" }, - { 0x708090, "slategrey" }, - { 0xfffafa, "snow" }, - { 0x00ff7f, "springgreen" }, - { 0x4682b4, "steelblue" }, - { 0xd2b48c, "tan" }, - { 0xd8bfd8, "thistle" }, - { 0xff6347, "tomato" }, - { 0x40e0d0, "turquoise" }, - { 0xee82ee, "violet" }, - { 0xf5deb3, "wheat" }, - { 0xf5f5f5, "whitesmoke" }, - { 0x9acd32, "yellowgreen" }, - // CSS Color Module Level 4 - { 0x663399, "rebeccapurple" }, - // (Fallback) - { 0x000000, nullptr } - }; - - for (size_t i = 0; web_colors[i].name; ++i) { - if (string == web_colors[i].name) - return Color::from_rgb(web_colors[i].color); - } - - if (string[0] != '#') - return {}; - - auto hex_nibble_to_u8 = [](char nibble) -> Optional<u8> { - if (!isxdigit(nibble)) - return {}; - if (nibble >= '0' && nibble <= '9') - return nibble - '0'; - return 10 + (tolower(nibble) - 'a'); - }; - - if (string.length() == 4) { - Optional<u8> r = hex_nibble_to_u8(string[1]); - Optional<u8> g = hex_nibble_to_u8(string[2]); - Optional<u8> b = hex_nibble_to_u8(string[3]); - if (!r.has_value() || !g.has_value() || !b.has_value()) - return {}; - return Color(r.value() * 17, g.value() * 17, b.value() * 17); - } - - if (string.length() == 5) { - Optional<u8> r = hex_nibble_to_u8(string[1]); - Optional<u8> g = hex_nibble_to_u8(string[2]); - Optional<u8> b = hex_nibble_to_u8(string[3]); - Optional<u8> a = hex_nibble_to_u8(string[4]); - if (!r.has_value() || !g.has_value() || !b.has_value() || !a.has_value()) - return {}; - return Color(r.value() * 17, g.value() * 17, b.value() * 17, a.value() * 17); - } - - if (string.length() != 7 && string.length() != 9) - return {}; - - auto to_hex = [&](char c1, char c2) -> Optional<u8> { - auto nib1 = hex_nibble_to_u8(c1); - auto nib2 = hex_nibble_to_u8(c2); - if (!nib1.has_value() || !nib2.has_value()) - return {}; - return nib1.value() << 4 | nib2.value(); - }; - - Optional<u8> r = to_hex(string[1], string[2]); - Optional<u8> g = to_hex(string[3], string[4]); - Optional<u8> b = to_hex(string[5], string[6]); - Optional<u8> a = string.length() == 9 ? to_hex(string[7], string[8]) : Optional<u8>(255); - - if (!r.has_value() || !g.has_value() || !b.has_value() || !a.has_value()) - return {}; - - return Color(r.value(), g.value(), b.value(), a.value()); -} diff --git a/Libraries/LibDraw/Color.h b/Libraries/LibDraw/Color.h deleted file mode 100644 index 395ffa4149..0000000000 --- a/Libraries/LibDraw/Color.h +++ /dev/null @@ -1,185 +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/Optional.h> -#include <AK/String.h> -#include <AK/Types.h> - -namespace Gfx { - -enum class ColorRole; -typedef u32 RGBA32; - -inline constexpr u32 make_rgb(u8 r, u8 g, u8 b) -{ - return ((r << 16) | (g << 8) | b); -} - -class Color { -public: - enum NamedColor { - Black, - White, - Red, - Green, - Cyan, - Blue, - Yellow, - Magenta, - DarkGray, - MidGray, - LightGray, - WarmGray, - DarkCyan, - DarkGreen, - DarkBlue, - DarkRed, - MidCyan, - MidGreen, - MidRed, - MidBlue, - MidMagenta, - }; - - Color() {} - Color(NamedColor); - Color(u8 r, u8 g, u8 b) - : m_value(0xff000000 | (r << 16) | (g << 8) | b) - { - } - Color(u8 r, u8 g, u8 b, u8 a) - : m_value((a << 24) | (r << 16) | (g << 8) | b) - { - } - - static Color from_rgb(unsigned rgb) { return Color(rgb | 0xff000000); } - static Color from_rgba(unsigned rgba) { return Color(rgba); } - - u8 red() const { return (m_value >> 16) & 0xff; } - u8 green() const { return (m_value >> 8) & 0xff; } - u8 blue() const { return m_value & 0xff; } - u8 alpha() const { return (m_value >> 24) & 0xff; } - - void set_alpha(u8 value) - { - m_value &= 0x00ffffff; - m_value |= value << 24; - } - - void set_red(u8 value) - { - m_value &= 0xff00ffff; - m_value |= value << 16; - } - - void set_green(u8 value) - { - m_value &= 0xffff00ff; - m_value |= value << 8; - } - - void set_blue(u8 value) - { - m_value &= 0xffffff00; - m_value |= value; - } - - Color with_alpha(u8 alpha) - { - return Color((m_value & 0x00ffffff) | alpha << 24); - } - - Color blend(Color source) const - { - if (!alpha() || source.alpha() == 255) - return source; - - if (!source.alpha()) - return *this; - - int d = 255 * (alpha() + source.alpha()) - alpha() * source.alpha(); - u8 r = (red() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.red()) / d; - u8 g = (green() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.green()) / d; - u8 b = (blue() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.blue()) / d; - u8 a = d / 255; - return Color(r, g, b, a); - } - - Color to_grayscale() const - { - int gray = (red() + green() + blue()) / 3; - return Color(gray, gray, gray, alpha()); - } - - Color darkened(float amount = 0.5f) const - { - return Color(red() * amount, green() * amount, blue() * amount, alpha()); - } - - Color lightened(float amount = 1.2f) const - { - return Color(min(255, (int)((float)red() * amount)), min(255, (int)((float)green() * amount)), min(255, (int)((float)blue() * amount)), alpha()); - } - - Color inverted() const - { - return Color(~red(), ~green(), ~blue()); - } - - RGBA32 value() const { return m_value; } - - bool operator==(const Color& other) const - { - return m_value == other.m_value; - } - - bool operator!=(const Color& other) const - { - return m_value != other.m_value; - } - - String to_string() const; - static Optional<Color> from_string(const StringView&); - -private: - explicit Color(RGBA32 rgba) - : m_value(rgba) - { - } - - RGBA32 m_value { 0 }; -}; - -inline const LogStream& operator<<(const LogStream& stream, Color value) -{ - return stream << value.to_string(); -} - -} - -using Gfx::Color; diff --git a/Libraries/LibDraw/DisjointRectSet.cpp b/Libraries/LibDraw/DisjointRectSet.cpp deleted file mode 100644 index af47224f74..0000000000 --- a/Libraries/LibDraw/DisjointRectSet.cpp +++ /dev/null @@ -1,75 +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. - */ - -#include <LibDraw/DisjointRectSet.h> - -namespace Gfx { - -void DisjointRectSet::add(const Rect& new_rect) -{ - for (auto& rect : m_rects) { - if (rect.contains(new_rect)) - return; - } - - m_rects.append(new_rect); - if (m_rects.size() > 1) - shatter(); -} - -void DisjointRectSet::shatter() -{ - Vector<Rect, 32> output; - output.ensure_capacity(m_rects.size()); - bool pass_had_intersections = false; - do { - pass_had_intersections = false; - output.clear_with_capacity(); - for (int i = 0; i < m_rects.size(); ++i) { - auto& r1 = m_rects[i]; - for (int j = 0; j < m_rects.size(); ++j) { - if (i == j) - continue; - auto& r2 = m_rects[j]; - if (!r1.intersects(r2)) - continue; - pass_had_intersections = true; - auto pieces = r1.shatter(r2); - for (auto& piece : pieces) - output.append(piece); - m_rects.remove(i); - for (; i < m_rects.size(); ++i) - output.append(m_rects[i]); - goto next_pass; - } - output.append(r1); - } - next_pass: - swap(output, m_rects); - } while (pass_had_intersections); -} - -} diff --git a/Libraries/LibDraw/DisjointRectSet.h b/Libraries/LibDraw/DisjointRectSet.h deleted file mode 100644 index 9a36abb43e..0000000000 --- a/Libraries/LibDraw/DisjointRectSet.h +++ /dev/null @@ -1,58 +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/Vector.h> -#include <LibDraw/Rect.h> - -namespace Gfx { - -class DisjointRectSet { -public: - DisjointRectSet() {} - ~DisjointRectSet() {} - DisjointRectSet(DisjointRectSet&& other) - : m_rects(move(other.m_rects)) - { - } - - void add(const Rect&); - - bool is_empty() const { return m_rects.is_empty(); } - int size() const { return m_rects.size(); } - - void clear() { m_rects.clear(); } - void clear_with_capacity() { m_rects.clear_with_capacity(); } - const Vector<Rect, 32>& rects() const { return m_rects; } - -private: - void shatter(); - - Vector<Rect, 32> m_rects; -}; - -} diff --git a/Libraries/LibDraw/Emoji.cpp b/Libraries/LibDraw/Emoji.cpp deleted file mode 100644 index fe8b7e9339..0000000000 --- a/Libraries/LibDraw/Emoji.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@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/HashMap.h> -#include <AK/String.h> -#include <LibDraw/Emoji.h> -#include <LibDraw/GraphicsBitmap.h> - -namespace Gfx { - -static HashMap<u32, RefPtr<Gfx::Bitmap>> s_emojis; - -const Bitmap* Emoji::emoji_for_codepoint(u32 codepoint) -{ - auto it = s_emojis.find(codepoint); - if (it != s_emojis.end()) - return (*it).value.ptr(); - - String path = String::format("/res/emoji/U+%X.png", codepoint); - - auto bitmap = Bitmap::load_from_file(path); - if (!bitmap) { - s_emojis.set(codepoint, nullptr); - return nullptr; - } - - s_emojis.set(codepoint, bitmap); - return bitmap.ptr(); -} - -} diff --git a/Libraries/LibDraw/Emoji.h b/Libraries/LibDraw/Emoji.h deleted file mode 100644 index 094f2050d7..0000000000 --- a/Libraries/LibDraw/Emoji.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@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/Types.h> - -namespace Gfx { - -class Bitmap; - -class Emoji { -public: - static const Gfx::Bitmap* emoji_for_codepoint(u32 codepoint); -}; - -} diff --git a/Libraries/LibDraw/FloatPoint.h b/Libraries/LibDraw/FloatPoint.h deleted file mode 100644 index 05f16c7cfc..0000000000 --- a/Libraries/LibDraw/FloatPoint.h +++ /dev/null @@ -1,149 +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 <LibDraw/Orientation.h> - -namespace Gfx { - -class FloatRect; - -class FloatPoint { -public: - FloatPoint() {} - FloatPoint(float x, float y) - : m_x(x) - , m_y(y) - { - } - float x() const { return m_x; } - float y() const { return m_y; } - - void set_x(float x) { m_x = x; } - void set_y(float y) { m_y = y; } - - void move_by(float dx, float dy) - { - m_x += dx; - m_y += dy; - } - - void move_by(const FloatPoint& delta) - { - move_by(delta.x(), delta.y()); - } - - FloatPoint translated(const FloatPoint& delta) const - { - FloatPoint point = *this; - point.move_by(delta); - return point; - } - - FloatPoint translated(float dx, float dy) const - { - FloatPoint point = *this; - point.move_by(dx, dy); - return point; - } - - void constrain(const FloatRect&); - - bool operator==(const FloatPoint& other) const - { - return m_x == other.m_x - && m_y == other.m_y; - } - - bool operator!=(const FloatPoint& other) const - { - return !(*this == other); - } - - FloatPoint operator-() const { return { -m_x, -m_y }; } - - FloatPoint operator-(const FloatPoint& other) const { return { m_x - other.m_x, m_y - other.m_y }; } - FloatPoint& operator-=(const FloatPoint& other) - { - m_x -= other.m_x; - m_y -= other.m_y; - return *this; - } - - FloatPoint& operator+=(const FloatPoint& other) - { - m_x += other.m_x; - m_y += other.m_y; - return *this; - } - FloatPoint operator+(const FloatPoint& other) const { return { m_x + other.m_x, m_y + other.m_y }; } - - String to_string() const { return String::format("[%g,%g]", x(), y()); } - - bool is_null() const { return !m_x && !m_y; } - - float primary_offset_for_orientation(Orientation orientation) const - { - return orientation == Orientation::Vertical ? y() : x(); - } - - void set_primary_offset_for_orientation(Orientation orientation, float value) - { - if (orientation == Orientation::Vertical) - set_y(value); - else - set_x(value); - } - - float secondary_offset_for_orientation(Orientation orientation) const - { - return orientation == Orientation::Vertical ? x() : y(); - } - - void set_secondary_offset_for_orientation(Orientation orientation, float value) - { - if (orientation == Orientation::Vertical) - set_x(value); - else - set_y(value); - } - -private: - float m_x { 0 }; - float m_y { 0 }; -}; - -inline const LogStream& operator<<(const LogStream& stream, const FloatPoint& value) -{ - return stream << value.to_string(); -} - -} - -using Gfx::FloatPoint; diff --git a/Libraries/LibDraw/FloatRect.h b/Libraries/LibDraw/FloatRect.h deleted file mode 100644 index 91ec03eee1..0000000000 --- a/Libraries/LibDraw/FloatRect.h +++ /dev/null @@ -1,332 +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 <LibDraw/FloatPoint.h> -#include <LibDraw/FloatSize.h> -#include <LibDraw/Orientation.h> -#include <LibDraw/Rect.h> -#include <LibDraw/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) - { - } - - 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 Rect 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()) }; -} - -} - -using Gfx::FloatRect; diff --git a/Libraries/LibDraw/FloatSize.h b/Libraries/LibDraw/FloatSize.h deleted file mode 100644 index 08376a5fc2..0000000000 --- a/Libraries/LibDraw/FloatSize.h +++ /dev/null @@ -1,119 +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 <LibDraw/Orientation.h> - -namespace Gfx { - -class FloatSize { -public: - FloatSize() {} - FloatSize(float w, float h) - : m_width(w) - , m_height(h) - { - } - - 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); } - -private: - float m_width { 0 }; - float m_height { 0 }; -}; - -inline const LogStream& operator<<(const LogStream& stream, const FloatSize& value) -{ - return stream << value.to_string(); -} - -} - -using Gfx::FloatSize; diff --git a/Libraries/LibDraw/Font.cpp b/Libraries/LibDraw/Font.cpp deleted file mode 100644 index d8ea312793..0000000000 --- a/Libraries/LibDraw/Font.cpp +++ /dev/null @@ -1,242 +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. - */ - -#include "Font.h" -#include "Emoji.h" -#include "GraphicsBitmap.h" -#include <AK/BufferStream.h> -#include <AK/MappedFile.h> -#include <AK/StdLibExtras.h> -#include <AK/Utf8View.h> -#include <AK/kmalloc.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <sys/mman.h> -#include <unistd.h> - -namespace Gfx { - -struct [[gnu::packed]] FontFileHeader -{ - char magic[4]; - u8 glyph_width; - u8 glyph_height; - u8 type; - u8 is_variable_width; - u8 glyph_spacing; - u8 unused[5]; - char name[64]; -}; - -Font& Font::default_font() -{ - static Font* s_default_font; - static const char* default_font_path = "/res/fonts/Katica10.font"; - if (!s_default_font) { - s_default_font = Font::load_from_file(default_font_path).leak_ref(); - ASSERT(s_default_font); - } - return *s_default_font; -} - -Font& Font::default_fixed_width_font() -{ - static Font* s_default_fixed_width_font; - static const char* default_fixed_width_font_path = "/res/fonts/CsillaThin7x10.font"; - if (!s_default_fixed_width_font) { - s_default_fixed_width_font = Font::load_from_file(default_fixed_width_font_path).leak_ref(); - ASSERT(s_default_fixed_width_font); - } - return *s_default_fixed_width_font; -} - -Font& Font::default_bold_fixed_width_font() -{ - static Font* font; - static const char* default_bold_fixed_width_font_path = "/res/fonts/CsillaBold7x10.font"; - if (!font) { - font = Font::load_from_file(default_bold_fixed_width_font_path).leak_ref(); - ASSERT(font); - } - return *font; -} - -Font& Font::default_bold_font() -{ - static Font* s_default_bold_font; - static const char* default_bold_font_path = "/res/fonts/KaticaBold10.font"; - if (!s_default_bold_font) { - s_default_bold_font = Font::load_from_file(default_bold_font_path).leak_ref(); - ASSERT(s_default_bold_font); - } - return *s_default_bold_font; -} - -RefPtr<Font> Font::clone() const -{ - size_t bytes_per_glyph = sizeof(u32) * glyph_height(); - // FIXME: This is leaked! - auto* new_rows = static_cast<unsigned*>(kmalloc(bytes_per_glyph * 256)); - memcpy(new_rows, m_rows, bytes_per_glyph * 256); - auto* new_widths = static_cast<u8*>(kmalloc(256)); - if (m_glyph_widths) - memcpy(new_widths, m_glyph_widths, 256); - else - memset(new_widths, m_glyph_width, 256); - return adopt(*new Font(m_name, new_rows, new_widths, m_fixed_width, m_glyph_width, m_glyph_height, m_glyph_spacing)); -} - -Font::Font(const StringView& name, unsigned* rows, u8* widths, bool is_fixed_width, u8 glyph_width, u8 glyph_height, u8 glyph_spacing) - : m_name(name) - , m_rows(rows) - , m_glyph_widths(widths) - , m_glyph_width(glyph_width) - , m_glyph_height(glyph_height) - , m_min_glyph_width(glyph_width) - , m_max_glyph_width(glyph_width) - , m_glyph_spacing(glyph_spacing) - , m_fixed_width(is_fixed_width) -{ - if (!m_fixed_width) { - u8 maximum = 0; - u8 minimum = 255; - for (int i = 0; i < 256; ++i) { - minimum = min(minimum, m_glyph_widths[i]); - maximum = max(maximum, m_glyph_widths[i]); - } - m_min_glyph_width = minimum; - m_max_glyph_width = maximum; - } -} - -Font::~Font() -{ -} - -RefPtr<Font> Font::load_from_memory(const u8* data) -{ - auto& header = *reinterpret_cast<const FontFileHeader*>(data); - if (memcmp(header.magic, "!Fnt", 4)) { - dbgprintf("header.magic != '!Fnt', instead it's '%c%c%c%c'\n", header.magic[0], header.magic[1], header.magic[2], header.magic[3]); - return nullptr; - } - if (header.name[63] != '\0') { - dbgprintf("Font name not fully null-terminated\n"); - return nullptr; - } - - size_t bytes_per_glyph = sizeof(unsigned) * header.glyph_height; - - auto* rows = const_cast<unsigned*>((const unsigned*)(data + sizeof(FontFileHeader))); - u8* widths = nullptr; - if (header.is_variable_width) - widths = (u8*)(rows) + 256 * bytes_per_glyph; - return adopt(*new Font(String(header.name), rows, widths, !header.is_variable_width, header.glyph_width, header.glyph_height, header.glyph_spacing)); -} - -RefPtr<Font> Font::load_from_file(const StringView& path) -{ - MappedFile mapped_file(path); - if (!mapped_file.is_valid()) - return nullptr; - - auto font = load_from_memory((const u8*)mapped_file.data()); - font->m_mapped_file = move(mapped_file); - return font; -} - -bool Font::write_to_file(const StringView& path) -{ - int fd = creat_with_path_length(path.characters_without_null_termination(), path.length(), 0644); - if (fd < 0) { - perror("open"); - return false; - } - - FontFileHeader header; - memset(&header, 0, sizeof(FontFileHeader)); - memcpy(header.magic, "!Fnt", 4); - header.glyph_width = m_glyph_width; - header.glyph_height = m_glyph_height; - header.type = 0; - header.is_variable_width = !m_fixed_width; - header.glyph_spacing = m_glyph_spacing; - memcpy(header.name, m_name.characters(), min(m_name.length(), (size_t)63)); - - size_t bytes_per_glyph = sizeof(unsigned) * m_glyph_height; - - auto buffer = ByteBuffer::create_uninitialized(sizeof(FontFileHeader) + (256 * bytes_per_glyph) + 256); - BufferStream stream(buffer); - - stream << ByteBuffer::wrap(&header, sizeof(FontFileHeader)); - stream << ByteBuffer::wrap(m_rows, (256 * bytes_per_glyph)); - stream << ByteBuffer::wrap(m_glyph_widths, 256); - - ASSERT(stream.at_end()); - ssize_t nwritten = write(fd, buffer.data(), buffer.size()); - ASSERT(nwritten == (ssize_t)buffer.size()); - int rc = close(fd); - ASSERT(rc == 0); - return true; -} - -int Font::glyph_or_emoji_width(u32 codepoint) const -{ - if (codepoint < 256) - return glyph_width((char)codepoint); - - if (m_fixed_width) - return m_glyph_width; - - auto* emoji = Emoji::emoji_for_codepoint(codepoint); - if (emoji == nullptr) - return glyph_width('?'); - return emoji->size().width(); -} - -int Font::width(const StringView& string) const -{ - Utf8View utf8 { string }; - return width(utf8); -} - -int Font::width(const Utf8View& utf8) const -{ - bool first = true; - int width = 0; - - for (u32 codepoint : utf8) { - if (!first) - width += glyph_spacing(); - first = false; - width += glyph_or_emoji_width(codepoint); - } - - return width; -} - -} diff --git a/Libraries/LibDraw/Font.h b/Libraries/LibDraw/Font.h deleted file mode 100644 index b164582e84..0000000000 --- a/Libraries/LibDraw/Font.h +++ /dev/null @@ -1,132 +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/MappedFile.h> -#include <AK/RefCounted.h> -#include <AK/RefPtr.h> -#include <AK/String.h> -#include <AK/Types.h> -#include <AK/Utf8View.h> -#include <LibDraw/Rect.h> - -namespace Gfx { - -// FIXME: Make a MutableGlyphBitmap buddy class for FontEditor instead? -class GlyphBitmap { - friend class Font; - -public: - const unsigned* rows() const { return m_rows; } - unsigned row(unsigned index) const { return m_rows[index]; } - - bool bit_at(int x, int y) const { return row(y) & (1 << x); } - void set_bit_at(int x, int y, bool b) - { - auto& mutable_row = const_cast<unsigned*>(m_rows)[y]; - if (b) - mutable_row |= 1 << x; - else - mutable_row &= ~(1 << x); - } - - Size size() const { return m_size; } - int width() const { return m_size.width(); } - int height() const { return m_size.height(); } - -private: - GlyphBitmap(const unsigned* rows, Size size) - : m_rows(rows) - , m_size(size) - { - } - - const unsigned* m_rows { nullptr }; - Size m_size; -}; - -class Font : public RefCounted<Font> { -public: - static Font& default_font(); - static Font& default_bold_font(); - - static Font& default_fixed_width_font(); - static Font& default_bold_fixed_width_font(); - - RefPtr<Font> clone() const; - - static RefPtr<Font> load_from_file(const StringView& path); - bool write_to_file(const StringView& path); - - ~Font(); - - GlyphBitmap glyph_bitmap(char ch) const { return GlyphBitmap(&m_rows[(u8)ch * m_glyph_height], { glyph_width(ch), m_glyph_height }); } - - u8 glyph_width(char ch) const { return m_fixed_width ? m_glyph_width : m_glyph_widths[(u8)ch]; } - int glyph_or_emoji_width(u32 codepoint) const; - u8 glyph_height() const { return m_glyph_height; } - u8 min_glyph_width() const { return m_min_glyph_width; } - u8 max_glyph_width() const { return m_max_glyph_width; } - int width(const StringView&) const; - int width(const Utf8View&) const; - - String name() const { return m_name; } - void set_name(const StringView& name) { m_name = name; } - - bool is_fixed_width() const { return m_fixed_width; } - void set_fixed_width(bool b) { m_fixed_width = b; } - - u8 glyph_spacing() const { return m_glyph_spacing; } - void set_glyph_spacing(u8 spacing) { m_glyph_spacing = spacing; } - - void set_glyph_width(char ch, u8 width) - { - ASSERT(m_glyph_widths); - m_glyph_widths[(u8)ch] = width; - } - -private: - Font(const StringView& name, unsigned* rows, u8* widths, bool is_fixed_width, u8 glyph_width, u8 glyph_height, u8 glyph_spacing); - - static RefPtr<Font> load_from_memory(const u8*); - - String m_name; - - unsigned* m_rows { nullptr }; - u8* m_glyph_widths { nullptr }; - MappedFile m_mapped_file; - - u8 m_glyph_width { 0 }; - u8 m_glyph_height { 0 }; - u8 m_min_glyph_width { 0 }; - u8 m_max_glyph_width { 0 }; - u8 m_glyph_spacing { 0 }; - - bool m_fixed_width { false }; -}; - -} diff --git a/Libraries/LibDraw/GIFLoader.cpp b/Libraries/LibDraw/GIFLoader.cpp deleted file mode 100644 index 2ef4ea59e8..0000000000 --- a/Libraries/LibDraw/GIFLoader.cpp +++ /dev/null @@ -1,265 +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. - */ - -#include <AK/BufferStream.h> -#include <AK/ByteBuffer.h> -#include <AK/FileSystemPath.h> -#include <AK/NonnullOwnPtrVector.h> -#include <LibDraw/GIFLoader.h> -#include <stdio.h> - -namespace Gfx { - -static RefPtr<Gfx::Bitmap> load_gif_impl(const u8*, size_t); - -RefPtr<Gfx::Bitmap> load_gif(const StringView& path) -{ - MappedFile mapped_file(path); - if (!mapped_file.is_valid()) - return nullptr; - auto bitmap = load_gif_impl((const u8*)mapped_file.data(), mapped_file.size()); - if (bitmap) - bitmap->set_mmap_name(String::format("GraphicsBitmap [%dx%d] - Decoded GIF: %s", bitmap->width(), bitmap->height(), canonicalized_path(path).characters())); - return bitmap; -} - -RefPtr<Gfx::Bitmap> load_gif_from_memory(const u8* data, size_t length) -{ - auto bitmap = load_gif_impl(data, length); - if (bitmap) - bitmap->set_mmap_name(String::format("GraphicsBitmap [%dx%d] - Decoded GIF: <memory>", bitmap->width(), bitmap->height())); - return bitmap; -} - -enum class GIFFormat { - GIF87a, - GIF89a, -}; - -struct RGB { - u8 r; - u8 g; - u8 b; -}; - -struct LogicalScreen { - u16 width; - u16 height; - RGB color_map[256]; -}; - -struct ImageDescriptor { - u16 x; - u16 y; - u16 width; - u16 height; - bool use_global_color_map; - RGB color_map[256]; - u8 lzw_min_code_size; - Vector<u8> lzw_encoded_bytes; -}; - -RefPtr<Gfx::Bitmap> load_gif_impl(const u8* data, size_t data_size) -{ - if (data_size < 32) - return nullptr; - - auto buffer = ByteBuffer::wrap(data, data_size); - BufferStream stream(buffer); - - static const char valid_header_87[] = "GIF87a"; - static const char valid_header_89[] = "GIF89a"; - - char header[6]; - for (int i = 0; i < 6; ++i) - stream >> header[i]; - - GIFFormat format; - if (!memcmp(header, valid_header_87, sizeof(header))) - format = GIFFormat::GIF87a; - else if (!memcmp(header, valid_header_89, sizeof(header))) - format = GIFFormat::GIF89a; - else - return nullptr; - - printf("Format is %s\n", format == GIFFormat::GIF89a ? "GIF89a" : "GIF87a"); - - LogicalScreen logical_screen; - stream >> logical_screen.width; - stream >> logical_screen.height; - if (stream.handle_read_failure()) - return nullptr; - - u8 gcm_info = 0; - stream >> gcm_info; - - if (stream.handle_read_failure()) - return nullptr; - - bool global_color_map_follows_descriptor = gcm_info & 0x80; - u8 bits_per_pixel = (gcm_info & 7) + 1; - u8 bits_of_color_resolution = (gcm_info >> 4) & 7; - - printf("LogicalScreen: %dx%d\n", logical_screen.width, logical_screen.height); - printf("global_color_map_follows_descriptor: %u\n", global_color_map_follows_descriptor); - printf("bits_per_pixel: %u\n", bits_per_pixel); - printf("bits_of_color_resolution: %u\n", bits_of_color_resolution); - - u8 background_color = 0; - stream >> background_color; - if (stream.handle_read_failure()) - return nullptr; - - printf("background_color: %u\n", background_color); - - u8 pixel_aspect_ratio = 0; - stream >> pixel_aspect_ratio; - if (stream.handle_read_failure()) - return nullptr; - - int color_map_entry_count = 1; - for (int i = 0; i < bits_per_pixel; ++i) - color_map_entry_count *= 2; - - printf("color_map_entry_count: %d\n", color_map_entry_count); - - for (int i = 0; i < color_map_entry_count; ++i) { - stream >> logical_screen.color_map[i].r; - stream >> logical_screen.color_map[i].g; - stream >> logical_screen.color_map[i].b; - } - - if (stream.handle_read_failure()) - return nullptr; - - for (int i = 0; i < color_map_entry_count; ++i) { - auto& rgb = logical_screen.color_map[i]; - printf("[%02x]: %s\n", i, Color(rgb.r, rgb.g, rgb.b).to_string().characters()); - } - - NonnullOwnPtrVector<ImageDescriptor> images; - - for (;;) { - u8 sentinel = 0; - stream >> sentinel; - printf("Sentinel: %02x\n", sentinel); - - if (sentinel == 0x21) { - u8 extension_type = 0; - stream >> extension_type; - if (stream.handle_read_failure()) - return nullptr; - - printf("Extension block of type %02x\n", extension_type); - - u8 sub_block_length = 0; - - for (;;) { - stream >> sub_block_length; - - if (stream.handle_read_failure()) - return nullptr; - - if (sub_block_length == 0) - break; - - u8 dummy; - for (u16 i = 0; i < sub_block_length; ++i) - stream >> dummy; - - if (stream.handle_read_failure()) - return nullptr; - } - continue; - } - - if (sentinel == 0x2c) { - images.append(make<ImageDescriptor>()); - auto& image = images.last(); - u8 packed_fields; - stream >> image.x; - stream >> image.y; - stream >> image.width; - stream >> image.height; - stream >> packed_fields; - if (stream.handle_read_failure()) - return nullptr; - printf("Image descriptor: %d,%d %dx%d, %02x\n", image.x, image.y, image.width, image.height, packed_fields); - - stream >> image.lzw_min_code_size; - - printf("min code size: %u\n", image.lzw_min_code_size); - - u8 lzw_encoded_bytes_expected = 0; - - for (;;) { - stream >> lzw_encoded_bytes_expected; - - if (stream.handle_read_failure()) - return nullptr; - - if (lzw_encoded_bytes_expected == 0) - break; - - u8 buffer[256]; - for (int i = 0; i < lzw_encoded_bytes_expected; ++i) { - stream >> buffer[i]; - } - - if (stream.handle_read_failure()) - return nullptr; - - for (int i = 0; i < lzw_encoded_bytes_expected; ++i) { - image.lzw_encoded_bytes.append(buffer[i]); - } - } - continue; - } - - if (sentinel == 0x3b) { - printf("Trailer! Awesome :)\n"); - break; - } - - return nullptr; - } - - // We exited the block loop after finding a trailer. We should have everything needed. - printf("Image count: %d\n", images.size()); - if (images.is_empty()) - return nullptr; - - for (int i = 0; i < images.size(); ++i) { - auto& image = images.at(i); - printf("Image %d: %d,%d %dx%d %d bytes LZW-encoded\n", i, image.x, image.y, image.width, image.height, image.lzw_encoded_bytes.size()); - - // FIXME: Decode the LZW-encoded bytes and turn them into an image. - } - - return nullptr; -} - -} diff --git a/Libraries/LibDraw/GIFLoader.h b/Libraries/LibDraw/GIFLoader.h deleted file mode 100644 index 06be29aa4b..0000000000 --- a/Libraries/LibDraw/GIFLoader.h +++ /dev/null @@ -1,53 +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 <LibDraw/GraphicsBitmap.h> -#include <LibDraw/ImageDecoder.h> - -namespace Gfx { - -RefPtr<Gfx::Bitmap> load_gif(const StringView& path); -RefPtr<Gfx::Bitmap> load_gif_from_memory(const u8*, size_t); - -struct GIFLoadingContext; - -class GIFImageDecoderPlugin final : public ImageDecoderPlugin { -public: - virtual ~GIFImageDecoderPlugin() override; - GIFImageDecoderPlugin(const u8*, size_t); - - virtual Size size() override; - virtual RefPtr<Gfx::Bitmap> bitmap() override; - virtual void set_volatile() override; - [[nodiscard]] virtual bool set_nonvolatile() override; - -private: - OwnPtr<GIFLoadingContext> m_context; -}; - -} diff --git a/Libraries/LibDraw/GraphicsBitmap.cpp b/Libraries/LibDraw/GraphicsBitmap.cpp deleted file mode 100644 index 7b5e00dd2b..0000000000 --- a/Libraries/LibDraw/GraphicsBitmap.cpp +++ /dev/null @@ -1,177 +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. - */ - -#include <AK/MappedFile.h> -#include <LibDraw/GraphicsBitmap.h> -#include <LibDraw/PNGLoader.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <sys/mman.h> -#include <unistd.h> - -namespace Gfx { - -NonnullRefPtr<Bitmap> Bitmap::create(Format format, const Size& size) -{ - return adopt(*new Bitmap(format, size, Purgeable::No)); -} - -NonnullRefPtr<Bitmap> Bitmap::create_purgeable(Format format, const Size& size) -{ - return adopt(*new Bitmap(format, size, Purgeable::Yes)); -} - -Bitmap::Bitmap(Format format, const Size& size, Purgeable purgeable) - : m_size(size) - , m_pitch(round_up_to_power_of_two(size.width() * sizeof(RGBA32), 16)) - , m_format(format) - , m_purgeable(purgeable == Purgeable::Yes) -{ - if (format == Format::Indexed8) - m_palette = new RGBA32[256]; - int map_flags = purgeable == Purgeable::Yes ? (MAP_PURGEABLE | MAP_PRIVATE) : (MAP_ANONYMOUS | MAP_PRIVATE); - m_data = (RGBA32*)mmap_with_name(nullptr, size_in_bytes(), PROT_READ | PROT_WRITE, map_flags, 0, 0, String::format("GraphicsBitmap [%dx%d]", width(), height()).characters()); - ASSERT(m_data && m_data != (void*)-1); - m_needs_munmap = true; -} - -NonnullRefPtr<Bitmap> Bitmap::create_wrapper(Format format, const Size& size, size_t pitch, RGBA32* data) -{ - return adopt(*new Bitmap(format, size, pitch, data)); -} - -RefPtr<Bitmap> Bitmap::load_from_file(const StringView& path) -{ - return load_png(path); -} - -RefPtr<Bitmap> Bitmap::load_from_file(Format format, const StringView& path, const Size& size) -{ - MappedFile mapped_file(path); - if (!mapped_file.is_valid()) - return nullptr; - return adopt(*new Bitmap(format, size, move(mapped_file))); -} - -Bitmap::Bitmap(Format format, const Size& size, size_t pitch, RGBA32* data) - : m_size(size) - , m_data(data) - , m_pitch(pitch) - , m_format(format) -{ - if (format == Format::Indexed8) - m_palette = new RGBA32[256]; -} - -Bitmap::Bitmap(Format format, const Size& size, MappedFile&& mapped_file) - : m_size(size) - , m_data((RGBA32*)mapped_file.data()) - , m_pitch(round_up_to_power_of_two(size.width() * sizeof(RGBA32), 16)) - , m_format(format) - , m_mapped_file(move(mapped_file)) -{ - ASSERT(format != Format::Indexed8); -} - -NonnullRefPtr<Bitmap> Bitmap::create_with_shared_buffer(Format format, NonnullRefPtr<SharedBuffer>&& shared_buffer, const Size& size) -{ - return adopt(*new Bitmap(format, move(shared_buffer), size)); -} - -Bitmap::Bitmap(Format format, NonnullRefPtr<SharedBuffer>&& shared_buffer, const Size& size) - : m_size(size) - , m_data((RGBA32*)shared_buffer->data()) - , m_pitch(round_up_to_power_of_two(size.width() * sizeof(RGBA32), 16)) - , m_format(format) - , m_shared_buffer(move(shared_buffer)) -{ - ASSERT(format != Format::Indexed8); -} - -NonnullRefPtr<Bitmap> Bitmap::to_shareable_bitmap() const -{ - if (m_shared_buffer) - return *this; - auto buffer = SharedBuffer::create_with_size(size_in_bytes()); - auto bitmap = Bitmap::create_with_shared_buffer(m_format, *buffer, m_size); - memcpy(buffer->data(), scanline(0), size_in_bytes()); - return bitmap; -} - -Bitmap::~Bitmap() -{ - if (m_needs_munmap) { - int rc = munmap(m_data, size_in_bytes()); - ASSERT(rc == 0); - } - m_data = nullptr; - delete[] m_palette; -} - -void Bitmap::set_mmap_name(const StringView& name) -{ - ASSERT(m_needs_munmap); - ::set_mmap_name(m_data, size_in_bytes(), String(name).characters()); -} - -void Bitmap::fill(Color color) -{ - ASSERT(m_format == Bitmap::Format::RGB32 || m_format == Bitmap::Format::RGBA32); - for (int y = 0; y < height(); ++y) { - auto* scanline = this->scanline(y); - fast_u32_fill(scanline, color.value(), width()); - } -} - -void Bitmap::set_volatile() -{ - ASSERT(m_purgeable); - if (m_volatile) - return; - int rc = madvise(m_data, size_in_bytes(), MADV_SET_VOLATILE); - if (rc < 0) { - perror("madvise(MADV_SET_VOLATILE)"); - ASSERT_NOT_REACHED(); - } - m_volatile = true; -} - -[[nodiscard]] bool Bitmap::set_nonvolatile() -{ - ASSERT(m_purgeable); - if (!m_volatile) - return true; - int rc = madvise(m_data, size_in_bytes(), MADV_SET_NONVOLATILE); - if (rc < 0) { - perror("madvise(MADV_SET_NONVOLATILE)"); - ASSERT_NOT_REACHED(); - } - m_volatile = false; - return rc == 0; -} - -} diff --git a/Libraries/LibDraw/GraphicsBitmap.h b/Libraries/LibDraw/GraphicsBitmap.h deleted file mode 100644 index 7c64eafd1b..0000000000 --- a/Libraries/LibDraw/GraphicsBitmap.h +++ /dev/null @@ -1,240 +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 "Color.h" -#include "Rect.h" -#include "Size.h" -#include <AK/MappedFile.h> -#include <AK/RefCounted.h> -#include <AK/RefPtr.h> -#include <AK/SharedBuffer.h> -#include <AK/String.h> -#include <AK/StringView.h> - -namespace Gfx { - -class Bitmap : public RefCounted<Bitmap> { -public: - enum class Format { - Invalid, - RGB32, - RGBA32, - Indexed8 - }; - - static NonnullRefPtr<Bitmap> create(Format, const Size&); - static NonnullRefPtr<Bitmap> create_purgeable(Format, const Size&); - static NonnullRefPtr<Bitmap> create_wrapper(Format, const Size&, size_t pitch, RGBA32*); - static RefPtr<Bitmap> load_from_file(const StringView& path); - static RefPtr<Bitmap> load_from_file(Format, const StringView& path, const Size&); - static NonnullRefPtr<Bitmap> create_with_shared_buffer(Format, NonnullRefPtr<SharedBuffer>&&, const Size&); - - NonnullRefPtr<Bitmap> to_shareable_bitmap() const; - - ~Bitmap(); - - RGBA32* scanline(int y); - const RGBA32* scanline(int y) const; - - u8* bits(int y); - const u8* bits(int y) const; - - Rect rect() const { return { {}, m_size }; } - Size size() const { return m_size; } - int width() const { return m_size.width(); } - int height() const { return m_size.height(); } - size_t pitch() const { return m_pitch; } - int shared_buffer_id() const { return m_shared_buffer ? m_shared_buffer->shared_buffer_id() : -1; } - - SharedBuffer* shared_buffer() { return m_shared_buffer.ptr(); } - const SharedBuffer* shared_buffer() const { return m_shared_buffer.ptr(); } - - unsigned bpp() const - { - switch (m_format) { - case Format::Indexed8: - return 8; - case Format::RGB32: - case Format::RGBA32: - return 32; - default: - ASSERT_NOT_REACHED(); - case Format::Invalid: - return 0; - } - } - - void fill(Color); - - bool has_alpha_channel() const { return m_format == Format::RGBA32; } - Format format() const { return m_format; } - - void set_mmap_name(const StringView&); - - size_t size_in_bytes() const { return m_pitch * m_size.height(); } - - Color palette_color(u8 index) const { return Color::from_rgba(m_palette[index]); } - void set_palette_color(u8 index, Color color) { m_palette[index] = color.value(); } - - template<Format> - Color get_pixel(int x, int y) const - { - (void)x; - (void)y; - ASSERT_NOT_REACHED(); - } - - Color get_pixel(int x, int y) const; - - Color get_pixel(const Point& position) const - { - return get_pixel(position.x(), position.y()); - } - - template<Format> - void set_pixel(int x, int y, Color) - { - (void)x; - (void)y; - ASSERT_NOT_REACHED(); - } - - void set_pixel(int x, int y, Color); - - void set_pixel(const Point& position, Color color) - { - set_pixel(position.x(), position.y(), color); - } - - bool is_purgeable() const { return m_purgeable; } - bool is_volatile() const { return m_volatile; } - void set_volatile(); - [[nodiscard]] bool set_nonvolatile(); - -private: - enum class Purgeable { No, - Yes }; - Bitmap(Format, const Size&, Purgeable); - Bitmap(Format, const Size&, size_t pitch, RGBA32*); - Bitmap(Format, const Size&, MappedFile&&); - Bitmap(Format, NonnullRefPtr<SharedBuffer>&&, const Size&); - - Size m_size; - RGBA32* m_data { nullptr }; - RGBA32* m_palette { nullptr }; - size_t m_pitch { 0 }; - Format m_format { Format::Invalid }; - bool m_needs_munmap { false }; - bool m_purgeable { false }; - bool m_volatile { false }; - MappedFile m_mapped_file; - RefPtr<SharedBuffer> m_shared_buffer; -}; - -inline RGBA32* Bitmap::scanline(int y) -{ - return reinterpret_cast<RGBA32*>((((u8*)m_data) + (y * m_pitch))); -} - -inline const RGBA32* Bitmap::scanline(int y) const -{ - return reinterpret_cast<const RGBA32*>((((const u8*)m_data) + (y * m_pitch))); -} - -inline const u8* Bitmap::bits(int y) const -{ - return reinterpret_cast<const u8*>(scanline(y)); -} - -inline u8* Bitmap::bits(int y) -{ - return reinterpret_cast<u8*>(scanline(y)); -} - -template<> -inline Color Bitmap::get_pixel<Bitmap::Format::RGB32>(int x, int y) const -{ - return Color::from_rgb(scanline(y)[x]); -} - -template<> -inline Color Bitmap::get_pixel<Bitmap::Format::RGBA32>(int x, int y) const -{ - return Color::from_rgba(scanline(y)[x]); -} - -template<> -inline Color Bitmap::get_pixel<Bitmap::Format::Indexed8>(int x, int y) const -{ - return Color::from_rgba(m_palette[bits(y)[x]]); -} - -inline Color Bitmap::get_pixel(int x, int y) const -{ - switch (m_format) { - case Format::RGB32: - return get_pixel<Format::RGB32>(x, y); - case Format::RGBA32: - return get_pixel<Format::RGBA32>(x, y); - case Format::Indexed8: - return get_pixel<Format::Indexed8>(x, y); - default: - ASSERT_NOT_REACHED(); - return {}; - } -} - -template<> -inline void Bitmap::set_pixel<Bitmap::Format::RGB32>(int x, int y, Color color) -{ - scanline(y)[x] = color.value(); -} - -template<> -inline void Bitmap::set_pixel<Bitmap::Format::RGBA32>(int x, int y, Color color) -{ - scanline(y)[x] = color.value(); -} - -inline void Bitmap::set_pixel(int x, int y, Color color) -{ - switch (m_format) { - case Format::RGB32: - set_pixel<Format::RGB32>(x, y, color); - break; - case Format::RGBA32: - set_pixel<Format::RGBA32>(x, y, color); - break; - case Format::Indexed8: - ASSERT_NOT_REACHED(); - default: - ASSERT_NOT_REACHED(); - } -} - -} diff --git a/Libraries/LibDraw/ImageDecoder.cpp b/Libraries/LibDraw/ImageDecoder.cpp deleted file mode 100644 index aae0dbfa01..0000000000 --- a/Libraries/LibDraw/ImageDecoder.cpp +++ /dev/null @@ -1,40 +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. - */ - -#include <LibDraw/ImageDecoder.h> -#include <LibDraw/PNGLoader.h> - -namespace Gfx { - -ImageDecoder::ImageDecoder(const u8* data, size_t size) -{ - m_plugin = make<PNGImageDecoderPlugin>(data, size); -} - -ImageDecoder::~ImageDecoder() -{ -} -} diff --git a/Libraries/LibDraw/ImageDecoder.h b/Libraries/LibDraw/ImageDecoder.h deleted file mode 100644 index d00a90c4dd..0000000000 --- a/Libraries/LibDraw/ImageDecoder.h +++ /dev/null @@ -1,70 +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/NonnullRefPtr.h> -#include <AK/OwnPtr.h> -#include <AK/RefCounted.h> -#include <LibDraw/Size.h> - -namespace Gfx { - -class Bitmap; - -class ImageDecoderPlugin { -public: - virtual ~ImageDecoderPlugin() {} - - virtual Size size() = 0; - virtual RefPtr<Gfx::Bitmap> bitmap() = 0; - - virtual void set_volatile() = 0; - [[nodiscard]] virtual bool set_nonvolatile() = 0; - -protected: - ImageDecoderPlugin() {} -}; - -class ImageDecoder : public RefCounted<ImageDecoder> { -public: - static NonnullRefPtr<ImageDecoder> create(const u8* data, size_t size) { return adopt(*new ImageDecoder(data, size)); } - ~ImageDecoder(); - - Size size() const { return m_plugin->size(); } - int width() const { return size().width(); } - int height() const { return size().height(); } - RefPtr<Gfx::Bitmap> bitmap() const { return m_plugin->bitmap(); } - void set_volatile() { m_plugin->set_volatile(); } - [[nodiscard]] bool set_nonvolatile() { return m_plugin->set_nonvolatile(); } - -private: - ImageDecoder(const u8*, size_t); - - mutable OwnPtr<ImageDecoderPlugin> m_plugin; -}; - -} diff --git a/Libraries/LibDraw/Makefile b/Libraries/LibDraw/Makefile deleted file mode 100644 index a0490675aa..0000000000 --- a/Libraries/LibDraw/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -OBJS = \ - CharacterBitmap.o \ - Color.o \ - DisjointRectSet.o \ - Font.o \ - GraphicsBitmap.o \ - Painter.o \ - PNGLoader.o \ - GIFLoader.o \ - ImageDecoder.o \ - Rect.o \ - StylePainter.o \ - SystemTheme.o \ - Palette.o \ - Emoji.o - -LIBRARY = libdraw.a - -install: - mkdir -p $(SERENITY_BASE_DIR)/Root/usr/include/LibDraw/ - cp *.h $(SERENITY_BASE_DIR)/Root/usr/include/LibDraw/ - cp $(LIBRARY) $(SERENITY_BASE_DIR)/Root/usr/lib/ - -include ../../Makefile.common diff --git a/Libraries/LibDraw/Orientation.h b/Libraries/LibDraw/Orientation.h deleted file mode 100644 index e83af3f530..0000000000 --- a/Libraries/LibDraw/Orientation.h +++ /dev/null @@ -1,38 +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 - -namespace Gfx { - -enum class Orientation { - Horizontal, - Vertical -}; - -} - -using Gfx::Orientation; diff --git a/Libraries/LibDraw/PNGLoader.cpp b/Libraries/LibDraw/PNGLoader.cpp deleted file mode 100644 index 68a9c585b8..0000000000 --- a/Libraries/LibDraw/PNGLoader.cpp +++ /dev/null @@ -1,721 +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. - */ - -#include <AK/FileSystemPath.h> -#include <AK/MappedFile.h> -#include <AK/NetworkOrdered.h> -#include <LibCore/puff.h> -#include <LibDraw/PNGLoader.h> -#include <fcntl.h> -#include <serenity.h> -#include <stdio.h> -#include <string.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <unistd.h> - -namespace Gfx { - -static const u8 png_header[8] = { 0x89, 'P', 'N', 'G', 13, 10, 26, 10 }; - -struct PNG_IHDR { - NetworkOrdered<u32> width; - NetworkOrdered<u32> height; - u8 bit_depth { 0 }; - u8 color_type { 0 }; - u8 compression_method { 0 }; - u8 filter_method { 0 }; - u8 interlace_method { 0 }; -}; - -static_assert(sizeof(PNG_IHDR) == 13); - -struct Scanline { - u8 filter { 0 }; - ByteBuffer data {}; -}; - -struct [[gnu::packed]] PaletteEntry -{ - u8 r; - u8 g; - u8 b; - //u8 a; -}; - -struct [[gnu::packed]] Triplet -{ - u8 r; - u8 g; - u8 b; -}; - -struct [[gnu::packed]] Triplet16 -{ - u16 r; - u16 g; - u16 b; -}; - -struct [[gnu::packed]] Quad16 -{ - u16 r; - u16 g; - u16 b; - u16 a; -}; - -struct PNGLoadingContext { - enum State { - NotDecoded = 0, - Error, - HeaderDecoded, - SizeDecoded, - ChunksDecoded, - BitmapDecoded, - }; - State state { State::NotDecoded }; - const u8* data { nullptr }; - size_t data_size { 0 }; - int width { -1 }; - int height { -1 }; - u8 bit_depth { 0 }; - u8 color_type { 0 }; - u8 compression_method { 0 }; - u8 filter_method { 0 }; - u8 interlace_method { 0 }; - u8 bytes_per_pixel { 0 }; - bool has_seen_zlib_header { false }; - bool has_alpha() const { return color_type & 4 || palette_transparency_data.size() > 0; } - Vector<Scanline> scanlines; - RefPtr<Gfx::Bitmap> bitmap; - u8* decompression_buffer { nullptr }; - int decompression_buffer_size { 0 }; - Vector<u8> compressed_data; - Vector<PaletteEntry> palette_data; - Vector<u8> palette_transparency_data; -}; - -class Streamer { -public: - Streamer(const u8* data, int size) - : m_original_data(data) - , m_original_size(size) - , m_data_ptr(data) - , m_size_remaining(size) - { - } - - template<typename T> - bool read(T& value) - { - if (m_size_remaining < (int)sizeof(T)) - return false; - value = *((const NetworkOrdered<T>*)m_data_ptr); - m_data_ptr += sizeof(T); - m_size_remaining -= sizeof(T); - return true; - } - - bool read_bytes(u8* buffer, int count) - { - if (m_size_remaining < count) - return false; - memcpy(buffer, m_data_ptr, count); - m_data_ptr += count; - m_size_remaining -= count; - return true; - } - - bool wrap_bytes(ByteBuffer& buffer, int count) - { - if (m_size_remaining < count) - return false; - buffer = ByteBuffer::wrap(m_data_ptr, count); - m_data_ptr += count; - m_size_remaining -= count; - return true; - } - - bool at_end() const { return !m_size_remaining; } - -private: - const u8* m_original_data; - int m_original_size; - const u8* m_data_ptr; - int m_size_remaining; -}; - -static RefPtr<Gfx::Bitmap> load_png_impl(const u8*, int); -static bool process_chunk(Streamer&, PNGLoadingContext& context, bool decode_size_only); - -RefPtr<Gfx::Bitmap> load_png(const StringView& path) -{ - MappedFile mapped_file(path); - if (!mapped_file.is_valid()) - return nullptr; - auto bitmap = load_png_impl((const u8*)mapped_file.data(), mapped_file.size()); - if (bitmap) - bitmap->set_mmap_name(String::format("GraphicsBitmap [%dx%d] - Decoded PNG: %s", bitmap->width(), bitmap->height(), canonicalized_path(path).characters())); - return bitmap; -} - -RefPtr<Gfx::Bitmap> load_png_from_memory(const u8* data, size_t length) -{ - auto bitmap = load_png_impl(data, length); - if (bitmap) - bitmap->set_mmap_name(String::format("GraphicsBitmap [%dx%d] - Decoded PNG: <memory>", bitmap->width(), bitmap->height())); - return bitmap; -} - -[[gnu::always_inline]] static inline u8 paeth_predictor(int a, int b, int c) -{ - int p = a + b - c; - int pa = abs(p - a); - int pb = abs(p - b); - int pc = abs(p - c); - if (pa <= pb && pa <= pc) - return a; - if (pb <= pc) - return b; - return c; -} - -union [[gnu::packed]] Pixel -{ - RGBA32 rgba { 0 }; - u8 v[4]; - struct { - u8 r; - u8 g; - u8 b; - u8 a; - }; -}; -static_assert(sizeof(Pixel) == 4); - -template<bool has_alpha, u8 filter_type> -[[gnu::always_inline]] static inline void unfilter_impl(Gfx::Bitmap& bitmap, int y, const void* dummy_scanline_data) -{ - auto* dummy_scanline = (const Pixel*)dummy_scanline_data; - if constexpr (filter_type == 0) { - auto* pixels = (Pixel*)bitmap.scanline(y); - for (int i = 0; i < bitmap.width(); ++i) { - auto& x = pixels[i]; - swap(x.r, x.b); - } - } - - if constexpr (filter_type == 1) { - auto* pixels = (Pixel*)bitmap.scanline(y); - swap(pixels[0].r, pixels[0].b); - for (int i = 1; i < bitmap.width(); ++i) { - auto& x = pixels[i]; - swap(x.r, x.b); - auto& a = (const Pixel&)pixels[i - 1]; - x.v[0] += a.v[0]; - x.v[1] += a.v[1]; - x.v[2] += a.v[2]; - if constexpr (has_alpha) - x.v[3] += a.v[3]; - } - return; - } - if constexpr (filter_type == 2) { - auto* pixels = (Pixel*)bitmap.scanline(y); - auto* pixels_y_minus_1 = y == 0 ? dummy_scanline : (Pixel*)bitmap.scanline(y - 1); - for (int i = 0; i < bitmap.width(); ++i) { - auto& x = pixels[i]; - swap(x.r, x.b); - const Pixel& b = pixels_y_minus_1[i]; - x.v[0] += b.v[0]; - x.v[1] += b.v[1]; - x.v[2] += b.v[2]; - if constexpr (has_alpha) - x.v[3] += b.v[3]; - } - return; - } - if constexpr (filter_type == 3) { - auto* pixels = (Pixel*)bitmap.scanline(y); - auto* pixels_y_minus_1 = y == 0 ? dummy_scanline : (Pixel*)bitmap.scanline(y - 1); - for (int i = 0; i < bitmap.width(); ++i) { - auto& x = pixels[i]; - swap(x.r, x.b); - Pixel a; - if (i != 0) - a = pixels[i - 1]; - const Pixel& b = pixels_y_minus_1[i]; - x.v[0] = x.v[0] + ((a.v[0] + b.v[0]) / 2); - x.v[1] = x.v[1] + ((a.v[1] + b.v[1]) / 2); - x.v[2] = x.v[2] + ((a.v[2] + b.v[2]) / 2); - if constexpr (has_alpha) - x.v[3] = x.v[3] + ((a.v[3] + b.v[3]) / 2); - } - return; - } - if constexpr (filter_type == 4) { - auto* pixels = (Pixel*)bitmap.scanline(y); - auto* pixels_y_minus_1 = y == 0 ? dummy_scanline : (Pixel*)bitmap.scanline(y - 1); - for (int i = 0; i < bitmap.width(); ++i) { - auto& x = pixels[i]; - swap(x.r, x.b); - Pixel a; - const Pixel& b = pixels_y_minus_1[i]; - Pixel c; - if (i != 0) { - a = pixels[i - 1]; - c = pixels_y_minus_1[i - 1]; - } - x.v[0] += paeth_predictor(a.v[0], b.v[0], c.v[0]); - x.v[1] += paeth_predictor(a.v[1], b.v[1], c.v[1]); - x.v[2] += paeth_predictor(a.v[2], b.v[2], c.v[2]); - if constexpr (has_alpha) - x.v[3] += paeth_predictor(a.v[3], b.v[3], c.v[3]); - } - } -} - -[[gnu::noinline]] static void unfilter(PNGLoadingContext& context) -{ - // First unpack the scanlines to RGBA: - switch (context.color_type) { - case 2: - if (context.bit_depth == 8) { - for (int y = 0; y < context.height; ++y) { - auto* triplets = (Triplet*)context.scanlines[y].data.data(); - for (int i = 0; i < context.width; ++i) { - auto& pixel = (Pixel&)context.bitmap->scanline(y)[i]; - pixel.r = triplets[i].r; - pixel.g = triplets[i].g; - pixel.b = triplets[i].b; - pixel.a = 0xff; - } - } - } else if (context.bit_depth == 16) { - for (int y = 0; y < context.height; ++y) { - auto* triplets = (Triplet16*)context.scanlines[y].data.data(); - for (int i = 0; i < context.width; ++i) { - auto& pixel = (Pixel&)context.bitmap->scanline(y)[i]; - pixel.r = triplets[i].r & 0xFF; - pixel.g = triplets[i].g & 0xFF; - pixel.b = triplets[i].b & 0xFF; - pixel.a = 0xff; - } - } - } else { - ASSERT_NOT_REACHED(); - } - break; - case 6: - if (context.bit_depth == 8) { - for (int y = 0; y < context.height; ++y) { - memcpy(context.bitmap->scanline(y), context.scanlines[y].data.data(), context.scanlines[y].data.size()); - } - } else if (context.bit_depth == 16) { - for (int y = 0; y < context.height; ++y) { - auto* triplets = (Quad16*)context.scanlines[y].data.data(); - for (int i = 0; i < context.width; ++i) { - auto& pixel = (Pixel&)context.bitmap->scanline(y)[i]; - pixel.r = triplets[i].r & 0xFF; - pixel.g = triplets[i].g & 0xFF; - pixel.b = triplets[i].b & 0xFF; - pixel.a = triplets[i].a & 0xFF; - } - } - } else { - ASSERT_NOT_REACHED(); - } - break; - case 3: - for (int y = 0; y < context.height; ++y) { - auto* palette_index = (u8*)context.scanlines[y].data.data(); - for (int i = 0; i < context.width; ++i) { - auto& pixel = (Pixel&)context.bitmap->scanline(y)[i]; - auto& color = context.palette_data.at((int)palette_index[i]); - auto transparency = context.palette_transparency_data.size() >= palette_index[i] + 1 - ? (int)context.palette_transparency_data.data()[palette_index[i]] - : 0xFF; - pixel.r = color.r; - pixel.g = color.g; - pixel.b = color.b; - pixel.a = transparency; - } - } - break; - default: - ASSERT_NOT_REACHED(); - break; - } - - auto dummy_scanline = ByteBuffer::create_zeroed(context.width * sizeof(RGBA32)); - - for (int y = 0; y < context.height; ++y) { - auto filter = context.scanlines[y].filter; - if (filter == 0) { - if (context.has_alpha()) - unfilter_impl<true, 0>(*context.bitmap, y, dummy_scanline.data()); - else - unfilter_impl<false, 0>(*context.bitmap, y, dummy_scanline.data()); - continue; - } - if (filter == 1) { - if (context.has_alpha()) - unfilter_impl<true, 1>(*context.bitmap, y, dummy_scanline.data()); - else - unfilter_impl<false, 1>(*context.bitmap, y, dummy_scanline.data()); - continue; - } - if (filter == 2) { - if (context.has_alpha()) - unfilter_impl<true, 2>(*context.bitmap, y, dummy_scanline.data()); - else - unfilter_impl<false, 2>(*context.bitmap, y, dummy_scanline.data()); - continue; - } - if (filter == 3) { - if (context.has_alpha()) - unfilter_impl<true, 3>(*context.bitmap, y, dummy_scanline.data()); - else - unfilter_impl<false, 3>(*context.bitmap, y, dummy_scanline.data()); - continue; - } - if (filter == 4) { - if (context.has_alpha()) - unfilter_impl<true, 4>(*context.bitmap, y, dummy_scanline.data()); - else - unfilter_impl<false, 4>(*context.bitmap, y, dummy_scanline.data()); - continue; - } - } -} - -static bool decode_png_header(PNGLoadingContext& context) -{ - if (context.state >= PNGLoadingContext::HeaderDecoded) - return true; - - if (memcmp(context.data, png_header, sizeof(png_header)) != 0) { - dbg() << "Invalid PNG header"; - context.state = PNGLoadingContext::State::Error; - return false; - } - - context.state = PNGLoadingContext::HeaderDecoded; - return true; -} - -static bool decode_png_size(PNGLoadingContext& context) -{ - if (context.state >= PNGLoadingContext::SizeDecoded) - return true; - - if (context.state < PNGLoadingContext::HeaderDecoded) { - if (!decode_png_header(context)) - return false; - } - - const u8* data_ptr = context.data + sizeof(png_header); - size_t data_remaining = context.data_size - sizeof(png_header); - - Streamer streamer(data_ptr, data_remaining); - while (!streamer.at_end()) { - if (!process_chunk(streamer, context, true)) { - context.state = PNGLoadingContext::State::Error; - return false; - } - if (context.width && context.height) { - context.state = PNGLoadingContext::State::SizeDecoded; - return true; - } - } - - return false; -} - -static bool decode_png_chunks(PNGLoadingContext& context) -{ - if (context.state >= PNGLoadingContext::State::ChunksDecoded) - return true; - - if (context.state < PNGLoadingContext::HeaderDecoded) { - if (!decode_png_header(context)) - return false; - } - - const u8* data_ptr = context.data + sizeof(png_header); - int data_remaining = context.data_size - sizeof(png_header); - - context.compressed_data.ensure_capacity(context.data_size); - - Streamer streamer(data_ptr, data_remaining); - while (!streamer.at_end()) { - if (!process_chunk(streamer, context, false)) { - context.state = PNGLoadingContext::State::Error; - return false; - } - } - - context.state = PNGLoadingContext::State::ChunksDecoded; - return true; -} - -static bool decode_png_bitmap(PNGLoadingContext& context) -{ - if (context.state < PNGLoadingContext::State::ChunksDecoded) { - if (!decode_png_chunks(context)) - return false; - } - - if (context.state >= PNGLoadingContext::State::BitmapDecoded) - return true; - - unsigned long srclen = context.compressed_data.size() - 6; - unsigned long destlen = context.decompression_buffer_size; - int ret = puff(context.decompression_buffer, &destlen, context.compressed_data.data() + 2, &srclen); - if (ret < 0) { - context.state = PNGLoadingContext::State::Error; - return false; - } - context.compressed_data.clear(); - - context.scanlines.ensure_capacity(context.height); - Streamer streamer(context.decompression_buffer, context.decompression_buffer_size); - for (int y = 0; y < context.height; ++y) { - u8 filter; - if (!streamer.read(filter)) { - context.state = PNGLoadingContext::State::Error; - return false; - } - - context.scanlines.append({ filter }); - auto& scanline_buffer = context.scanlines.last().data; - if (!streamer.wrap_bytes(scanline_buffer, context.width * context.bytes_per_pixel)) { - context.state = PNGLoadingContext::State::Error; - return false; - } - } - - context.bitmap = Bitmap::create_purgeable(context.has_alpha() ? Bitmap::Format::RGBA32 : Bitmap::Format::RGB32, { context.width, context.height }); - - unfilter(context); - - munmap(context.decompression_buffer, context.decompression_buffer_size); - context.decompression_buffer = nullptr; - context.decompression_buffer_size = 0; - - context.state = PNGLoadingContext::State::BitmapDecoded; - return true; -} - -static RefPtr<Gfx::Bitmap> load_png_impl(const u8* data, int data_size) -{ - PNGLoadingContext context; - context.data = data; - context.data_size = data_size; - - if (!decode_png_chunks(context)) - return nullptr; - - if (!decode_png_bitmap(context)) - return nullptr; - - return context.bitmap; -} - -static bool process_IHDR(const ByteBuffer& data, PNGLoadingContext& context, bool decode_size_only = false) -{ - if (data.size() < (int)sizeof(PNG_IHDR)) - return false; - auto& ihdr = *(const PNG_IHDR*)data.data(); - context.width = ihdr.width; - context.height = ihdr.height; - context.bit_depth = ihdr.bit_depth; - context.color_type = ihdr.color_type; - context.compression_method = ihdr.compression_method; - context.filter_method = ihdr.filter_method; - context.interlace_method = ihdr.interlace_method; - -#ifdef PNG_DEBUG - printf("PNG: %dx%d (%d bpp)\n", context.width, context.height, context.bit_depth); - printf(" Color type: %d\n", context.color_type); - printf("Compress Method: %d\n", context.compression_method); - printf(" Filter Method: %d\n", context.filter_method); - printf(" Interlace type: %d\n", context.interlace_method); -#endif - - // FIXME: Implement Adam7 deinterlacing - if (context.interlace_method != 0) { - dbgprintf("PNGLoader::process_IHDR: Interlaced PNGs not currently supported.\n"); - return false; - } - - switch (context.color_type) { - case 0: // Each pixel is a grayscale sample. - case 4: // Each pixel is a grayscale sample, followed by an alpha sample. - // FIXME: Implement grayscale PNG support. - dbgprintf("PNGLoader::process_IHDR: Unsupported grayscale format.\n"); - return false; - case 2: - context.bytes_per_pixel = 3 * (ihdr.bit_depth / 8); - break; - case 3: // Each pixel is a palette index; a PLTE chunk must appear. - // FIXME: Implement support for 1/2/4 bit palette based images. - if (ihdr.bit_depth != 8) { - dbgprintf("PNGLoader::process_IHDR: Unsupported index-based format (%d bpp).\n", context.bit_depth); - return false; - } - context.bytes_per_pixel = 1; - break; - case 6: - context.bytes_per_pixel = 4 * (ihdr.bit_depth / 8); - break; - default: - ASSERT_NOT_REACHED(); - } - - if (!decode_size_only) { - context.decompression_buffer_size = (context.width * context.height * context.bytes_per_pixel + context.height); - context.decompression_buffer = (u8*)mmap_with_name(nullptr, context.decompression_buffer_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0, "PNG decompression buffer"); - } - return true; -} - -static bool process_IDAT(const ByteBuffer& data, PNGLoadingContext& context) -{ - context.compressed_data.append(data.data(), data.size()); - return true; -} - -static bool process_PLTE(const ByteBuffer& data, PNGLoadingContext& context) -{ - context.palette_data.append((const PaletteEntry*)data.data(), data.size() / 3); - return true; -} - -static bool process_tRNS(const ByteBuffer& data, PNGLoadingContext& context) -{ - switch (context.color_type) { - case 3: - context.palette_transparency_data.append(data.data(), data.size()); - break; - } - return true; -} - -static bool process_chunk(Streamer& streamer, PNGLoadingContext& context, bool decode_size_only) -{ - u32 chunk_size; - if (!streamer.read(chunk_size)) { - printf("Bail at chunk_size\n"); - return false; - } - u8 chunk_type[5]; - chunk_type[4] = '\0'; - if (!streamer.read_bytes(chunk_type, 4)) { - printf("Bail at chunk_type\n"); - return false; - } - ByteBuffer chunk_data; - if (!streamer.wrap_bytes(chunk_data, chunk_size)) { - printf("Bail at chunk_data\n"); - return false; - } - u32 chunk_crc; - if (!streamer.read(chunk_crc)) { - printf("Bail at chunk_crc\n"); - return false; - } -#ifdef PNG_DEBUG - printf("Chunk type: '%s', size: %u, crc: %x\n", chunk_type, chunk_size, chunk_crc); -#endif - - if (!strcmp((const char*)chunk_type, "IHDR")) - return process_IHDR(chunk_data, context, decode_size_only); - if (!strcmp((const char*)chunk_type, "IDAT")) - return process_IDAT(chunk_data, context); - if (!strcmp((const char*)chunk_type, "PLTE")) - return process_PLTE(chunk_data, context); - if (!strcmp((const char*)chunk_type, "tRNS")) - return process_tRNS(chunk_data, context); - return true; -} - -PNGImageDecoderPlugin::PNGImageDecoderPlugin(const u8* data, size_t size) -{ - m_context = make<PNGLoadingContext>(); - m_context->data = data; - m_context->data_size = size; -} - -PNGImageDecoderPlugin::~PNGImageDecoderPlugin() -{ -} - -Size PNGImageDecoderPlugin::size() -{ - if (m_context->state == PNGLoadingContext::State::Error) - return {}; - - if (m_context->state < PNGLoadingContext::State::SizeDecoded) { - bool success = decode_png_size(*m_context); - if (!success) - return {}; - } - - return { m_context->width, m_context->height }; -} - -RefPtr<Gfx::Bitmap> PNGImageDecoderPlugin::bitmap() -{ - if (m_context->state == PNGLoadingContext::State::Error) - return nullptr; - - if (m_context->state < PNGLoadingContext::State::BitmapDecoded) { - // NOTE: This forces the chunk decoding to happen. - bool success = decode_png_bitmap(*m_context); - if (!success) - return nullptr; - } - - ASSERT(m_context->bitmap); - return m_context->bitmap; -} - -void PNGImageDecoderPlugin::set_volatile() -{ - if (m_context->bitmap) - m_context->bitmap->set_volatile(); -} - -bool PNGImageDecoderPlugin::set_nonvolatile() -{ - if (!m_context->bitmap) - return false; - return m_context->bitmap->set_nonvolatile(); -} - -} diff --git a/Libraries/LibDraw/PNGLoader.h b/Libraries/LibDraw/PNGLoader.h deleted file mode 100644 index c3d5f8e3f8..0000000000 --- a/Libraries/LibDraw/PNGLoader.h +++ /dev/null @@ -1,53 +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 <LibDraw/GraphicsBitmap.h> -#include <LibDraw/ImageDecoder.h> - -namespace Gfx { - -RefPtr<Gfx::Bitmap> load_png(const StringView& path); -RefPtr<Gfx::Bitmap> load_png_from_memory(const u8*, size_t); - -struct PNGLoadingContext; - -class PNGImageDecoderPlugin final : public ImageDecoderPlugin { -public: - virtual ~PNGImageDecoderPlugin() override; - PNGImageDecoderPlugin(const u8*, size_t); - - virtual Size size() override; - virtual RefPtr<Gfx::Bitmap> bitmap() override; - virtual void set_volatile() override; - [[nodiscard]] virtual bool set_nonvolatile() override; - -private: - OwnPtr<PNGLoadingContext> m_context; -}; - -} diff --git a/Libraries/LibDraw/Painter.cpp b/Libraries/LibDraw/Painter.cpp deleted file mode 100644 index 4cc8bbc42d..0000000000 --- a/Libraries/LibDraw/Painter.cpp +++ /dev/null @@ -1,958 +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. - */ - -#include "Painter.h" -#include "Emoji.h" -#include "Font.h" -#include "GraphicsBitmap.h" -#include <AK/Assertions.h> -#include <AK/StdLibExtras.h> -#include <AK/StringBuilder.h> -#include <AK/Utf8View.h> -#include <LibDraw/CharacterBitmap.h> -#include <math.h> -#include <stdio.h> -#include <unistd.h> - -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC optimize("O3") -#endif - -#ifndef ALWAYS_INLINE -#if __has_attribute(always_inline) -#define ALWAYS_INLINE __attribute__((always_inline)) -#else -#define ALWAYS_INLINE inline -#endif -#endif - -namespace Gfx { - -template<Bitmap::Format format = Bitmap::Format::Invalid> -static ALWAYS_INLINE Color get_pixel(const Gfx::Bitmap& bitmap, int x, int y) -{ - if constexpr (format == Bitmap::Format::Indexed8) - return bitmap.palette_color(bitmap.bits(y)[x]); - if constexpr (format == Bitmap::Format::RGB32) - return Color::from_rgb(bitmap.scanline(y)[x]); - if constexpr (format == Bitmap::Format::RGBA32) - return Color::from_rgba(bitmap.scanline(y)[x]); - return bitmap.get_pixel(x, y); -} - -Painter::Painter(Gfx::Bitmap& bitmap) - : m_target(bitmap) -{ - m_state_stack.append(State()); - state().font = &Font::default_font(); - state().clip_rect = { { 0, 0 }, bitmap.size() }; - m_clip_origin = state().clip_rect; -} - -Painter::~Painter() -{ -} - -void Painter::fill_rect_with_draw_op(const Rect& a_rect, Color color) -{ - auto rect = a_rect.translated(translation()).intersected(clip_rect()); - if (rect.is_empty()) - return; - - RGBA32* dst = m_target->scanline(rect.top()) + rect.left(); - const size_t dst_skip = m_target->pitch() / sizeof(RGBA32); - - for (int i = rect.height() - 1; i >= 0; --i) { - for (int j = 0; j < rect.width(); ++j) - set_pixel_with_draw_op(dst[j], color); - dst += dst_skip; - } -} - -void Painter::clear_rect(const Rect& a_rect, Color color) -{ - auto rect = a_rect.translated(translation()).intersected(clip_rect()); - if (rect.is_empty()) - return; - - ASSERT(m_target->rect().contains(rect)); - - RGBA32* dst = m_target->scanline(rect.top()) + rect.left(); - const size_t dst_skip = m_target->pitch() / sizeof(RGBA32); - - for (int i = rect.height() - 1; i >= 0; --i) { - fast_u32_fill(dst, color.value(), rect.width()); - dst += dst_skip; - } -} - -void Painter::fill_rect(const Rect& a_rect, Color color) -{ - if (color.alpha() == 0) - return; - - if (draw_op() != DrawOp::Copy) { - fill_rect_with_draw_op(a_rect, color); - return; - } - - if (color.alpha() == 0xff) { - clear_rect(a_rect, color); - return; - } - - auto rect = a_rect.translated(translation()).intersected(clip_rect()); - if (rect.is_empty()) - return; - - ASSERT(m_target->rect().contains(rect)); - - RGBA32* dst = m_target->scanline(rect.top()) + rect.left(); - const size_t dst_skip = m_target->pitch() / sizeof(RGBA32); - - for (int i = rect.height() - 1; i >= 0; --i) { - for (int j = 0; j < rect.width(); ++j) - dst[j] = Color::from_rgba(dst[j]).blend(color).value(); - dst += dst_skip; - } -} - -void Painter::fill_rect_with_gradient(const Rect& a_rect, Color gradient_start, Color gradient_end) -{ -#ifdef NO_FPU - return fill_rect(a_rect, gradient_start); -#endif - auto rect = a_rect.translated(translation()); - auto clipped_rect = Rect::intersection(rect, clip_rect()); - if (clipped_rect.is_empty()) - return; - - int x_offset = clipped_rect.x() - rect.x(); - - RGBA32* dst = m_target->scanline(clipped_rect.top()) + clipped_rect.left(); - const size_t dst_skip = m_target->pitch() / sizeof(RGBA32); - - float increment = (1.0 / ((rect.width()) / 255.0)); - - int r2 = gradient_start.red(); - int g2 = gradient_start.green(); - int b2 = gradient_start.blue(); - int r1 = gradient_end.red(); - int g1 = gradient_end.green(); - int b1 = gradient_end.blue(); - - for (int i = clipped_rect.height() - 1; i >= 0; --i) { - float c = x_offset * increment; - for (int j = 0; j < clipped_rect.width(); ++j) { - dst[j] = Color( - r1 / 255.0 * c + r2 / 255.0 * (255 - c), - g1 / 255.0 * c + g2 / 255.0 * (255 - c), - b1 / 255.0 * c + b2 / 255.0 * (255 - c)) - .value(); - c += increment; - } - dst += dst_skip; - } -} - -void Painter::draw_ellipse_intersecting(const Rect& rect, Color color, int thickness) -{ - constexpr int number_samples = 100; // FIXME: dynamically work out the number of samples based upon the rect size - double increment = M_PI / number_samples; - - auto ellipse_x = [&](double theta) -> int { - return (cos(theta) * rect.width() / sqrt(2)) + rect.center().x(); - }; - - auto ellipse_y = [&](double theta) -> int { - return (sin(theta) * rect.height() / sqrt(2)) + rect.center().y(); - }; - - for (float theta = 0; theta < 2 * M_PI; theta += increment) { - draw_line({ ellipse_x(theta), ellipse_y(theta) }, { ellipse_x(theta + increment), ellipse_y(theta + increment) }, color, thickness); - } -} - -void Painter::draw_rect(const Rect& a_rect, Color color, bool rough) -{ - Rect rect = a_rect.translated(translation()); - auto clipped_rect = rect.intersected(clip_rect()); - if (clipped_rect.is_empty()) - return; - - int min_y = clipped_rect.top(); - int max_y = clipped_rect.bottom(); - - if (rect.top() >= clipped_rect.top() && rect.top() <= clipped_rect.bottom()) { - int start_x = rough ? max(rect.x() + 1, clipped_rect.x()) : clipped_rect.x(); - int width = rough ? min(rect.width() - 2, clipped_rect.width()) : clipped_rect.width(); - fast_u32_fill(m_target->scanline(rect.top()) + start_x, color.value(), width); - ++min_y; - } - if (rect.bottom() >= clipped_rect.top() && rect.bottom() <= clipped_rect.bottom()) { - int start_x = rough ? max(rect.x() + 1, clipped_rect.x()) : clipped_rect.x(); - int width = rough ? min(rect.width() - 2, clipped_rect.width()) : clipped_rect.width(); - fast_u32_fill(m_target->scanline(rect.bottom()) + start_x, color.value(), width); - --max_y; - } - - bool draw_left_side = rect.left() >= clipped_rect.left(); - bool draw_right_side = rect.right() == clipped_rect.right(); - - if (draw_left_side && draw_right_side) { - // Specialized loop when drawing both sides. - for (int y = min_y; y <= max_y; ++y) { - auto* bits = m_target->scanline(y); - bits[rect.left()] = color.value(); - bits[rect.right()] = color.value(); - } - } else { - for (int y = min_y; y <= max_y; ++y) { - auto* bits = m_target->scanline(y); - if (draw_left_side) - bits[rect.left()] = color.value(); - if (draw_right_side) - bits[rect.right()] = color.value(); - } - } -} - -void Painter::draw_bitmap(const Point& p, const CharacterBitmap& bitmap, Color color) -{ - auto rect = Rect(p, bitmap.size()).translated(translation()); - auto clipped_rect = rect.intersected(clip_rect()); - if (clipped_rect.is_empty()) - return; - const int first_row = clipped_rect.top() - rect.top(); - const int last_row = clipped_rect.bottom() - rect.top(); - const int first_column = clipped_rect.left() - rect.left(); - const int last_column = clipped_rect.right() - rect.left(); - RGBA32* dst = m_target->scanline(clipped_rect.y()) + clipped_rect.x(); - const size_t dst_skip = m_target->pitch() / sizeof(RGBA32); - const char* bitmap_row = &bitmap.bits()[first_row * bitmap.width() + first_column]; - const size_t bitmap_skip = bitmap.width(); - - for (int row = first_row; row <= last_row; ++row) { - for (int j = 0; j <= (last_column - first_column); ++j) { - char fc = bitmap_row[j]; - if (fc == '#') - dst[j] = color.value(); - } - bitmap_row += bitmap_skip; - dst += dst_skip; - } -} - -void Painter::draw_bitmap(const Point& p, const GlyphBitmap& bitmap, Color color) -{ - auto dst_rect = Rect(p, bitmap.size()).translated(translation()); - auto clipped_rect = dst_rect.intersected(clip_rect()); - if (clipped_rect.is_empty()) - return; - const int first_row = clipped_rect.top() - dst_rect.top(); - const int last_row = clipped_rect.bottom() - dst_rect.top(); - const int first_column = clipped_rect.left() - dst_rect.left(); - const int last_column = clipped_rect.right() - dst_rect.left(); - RGBA32* dst = m_target->scanline(clipped_rect.y()) + clipped_rect.x(); - const size_t dst_skip = m_target->pitch() / sizeof(RGBA32); - - for (int row = first_row; row <= last_row; ++row) { - for (int j = 0; j <= (last_column - first_column); ++j) { - if (bitmap.bit_at(j + first_column, row)) - dst[j] = color.value(); - } - dst += dst_skip; - } -} - -void Painter::blit_scaled(const Rect& dst_rect_raw, const Gfx::Bitmap& source, const Rect& src_rect, float hscale, float vscale) -{ - auto dst_rect = Rect(dst_rect_raw.location(), dst_rect_raw.size()).translated(translation()); - auto clipped_rect = dst_rect.intersected(clip_rect()); - if (clipped_rect.is_empty()) - return; - const int first_row = (clipped_rect.top() - dst_rect.top()); - const int last_row = (clipped_rect.bottom() - dst_rect.top()); - const int first_column = (clipped_rect.left() - dst_rect.left()); - RGBA32* dst = m_target->scanline(clipped_rect.y()) + clipped_rect.x(); - const size_t dst_skip = m_target->pitch() / sizeof(RGBA32); - - int x_start = first_column + src_rect.left(); - for (int row = first_row; row <= last_row; ++row) { - int sr = (row + src_rect.top()) * vscale; - if (sr >= source.size().height() || sr < 0) { - dst += dst_skip; - continue; - } - const RGBA32* sl = source.scanline(sr); - for (int x = x_start; x < clipped_rect.width() + x_start; ++x) { - int sx = x * hscale; - if (sx < source.size().width() && sx >= 0) - dst[x - x_start] = sl[sx]; - } - dst += dst_skip; - } - return; -} - -void Painter::blit_with_opacity(const Point& position, const Gfx::Bitmap& source, const Rect& src_rect, float opacity) -{ - ASSERT(!m_target->has_alpha_channel()); - - if (!opacity) - return; - if (opacity >= 1.0f) - return blit(position, source, src_rect); - - u8 alpha = 255 * opacity; - - Rect safe_src_rect = Rect::intersection(src_rect, source.rect()); - Rect dst_rect(position, safe_src_rect.size()); - dst_rect.move_by(state().translation); - auto clipped_rect = Rect::intersection(dst_rect, clip_rect()); - if (clipped_rect.is_empty()) - return; - const int first_row = clipped_rect.top() - dst_rect.top(); - const int last_row = clipped_rect.bottom() - dst_rect.top(); - const int first_column = clipped_rect.left() - dst_rect.left(); - const int last_column = clipped_rect.right() - dst_rect.left(); - RGBA32* dst = m_target->scanline(clipped_rect.y()) + clipped_rect.x(); - const RGBA32* src = source.scanline(src_rect.top() + first_row) + src_rect.left() + first_column; - const size_t dst_skip = m_target->pitch() / sizeof(RGBA32); - const unsigned src_skip = source.pitch() / sizeof(RGBA32); - - for (int row = first_row; row <= last_row; ++row) { - for (int x = 0; x <= (last_column - first_column); ++x) { - Color src_color_with_alpha = Color::from_rgb(src[x]); - src_color_with_alpha.set_alpha(alpha); - Color dst_color = Color::from_rgb(dst[x]); - dst[x] = dst_color.blend(src_color_with_alpha).value(); - } - dst += dst_skip; - src += src_skip; - } -} - -void Painter::blit_dimmed(const Point& position, const Gfx::Bitmap& source, const Rect& src_rect) -{ - Rect safe_src_rect = src_rect.intersected(source.rect()); - auto dst_rect = Rect(position, safe_src_rect.size()).translated(translation()); - auto clipped_rect = dst_rect.intersected(clip_rect()); - if (clipped_rect.is_empty()) - return; - const int first_row = clipped_rect.top() - dst_rect.top(); - const int last_row = clipped_rect.bottom() - dst_rect.top(); - const int first_column = clipped_rect.left() - dst_rect.left(); - const int last_column = clipped_rect.right() - dst_rect.left(); - RGBA32* dst = m_target->scanline(clipped_rect.y()) + clipped_rect.x(); - const RGBA32* src = source.scanline(src_rect.top() + first_row) + src_rect.left() + first_column; - const size_t dst_skip = m_target->pitch() / sizeof(RGBA32); - const size_t src_skip = source.pitch() / sizeof(RGBA32); - - for (int row = first_row; row <= last_row; ++row) { - for (int x = 0; x <= (last_column - first_column); ++x) { - u8 alpha = Color::from_rgba(src[x]).alpha(); - if (alpha == 0xff) - dst[x] = Color::from_rgba(src[x]).to_grayscale().lightened().value(); - else if (!alpha) - continue; - else - dst[x] = Color::from_rgba(dst[x]).blend(Color::from_rgba(src[x]).to_grayscale().lightened()).value(); - } - dst += dst_skip; - src += src_skip; - } -} - -void Painter::draw_tiled_bitmap(const Rect& a_dst_rect, const Gfx::Bitmap& source) -{ - auto dst_rect = a_dst_rect.translated(translation()); - auto clipped_rect = dst_rect.intersected(clip_rect()); - if (clipped_rect.is_empty()) - return; - const int first_row = (clipped_rect.top() - dst_rect.top()); - const int last_row = (clipped_rect.bottom() - dst_rect.top()); - const int first_column = (clipped_rect.left() - dst_rect.left()); - RGBA32* dst = m_target->scanline(clipped_rect.y()) + clipped_rect.x(); - const size_t dst_skip = m_target->pitch() / sizeof(RGBA32); - - if (source.format() == Bitmap::Format::RGB32 || source.format() == Bitmap::Format::RGBA32) { - int x_start = first_column + a_dst_rect.left(); - for (int row = first_row; row <= last_row; ++row) { - const RGBA32* sl = source.scanline((row + a_dst_rect.top()) - % source.size().height()); - for (int x = x_start; x < clipped_rect.width() + x_start; ++x) { - dst[x - x_start] = sl[x % source.size().width()]; - } - dst += dst_skip; - } - return; - } - - ASSERT_NOT_REACHED(); -} - -void Painter::blit_offset(const Point& position, - const Gfx::Bitmap& source, - const Rect& src_rect, - const Point& offset) -{ - auto dst_rect = Rect(position, src_rect.size()).translated(translation()); - auto clipped_rect = dst_rect.intersected(clip_rect()); - if (clipped_rect.is_empty()) - return; - const int first_row = (clipped_rect.top() - dst_rect.top()); - const int last_row = (clipped_rect.bottom() - dst_rect.top()); - const int first_column = (clipped_rect.left() - dst_rect.left()); - RGBA32* dst = m_target->scanline(clipped_rect.y()) + clipped_rect.x(); - const size_t dst_skip = m_target->pitch() / sizeof(RGBA32); - - if (source.format() == Bitmap::Format::RGB32 || source.format() == Bitmap::Format::RGBA32) { - int x_start = first_column + src_rect.left(); - for (int row = first_row; row <= last_row; ++row) { - int sr = row - offset.y() + src_rect.top(); - if (sr >= source.size().height() || sr < 0) { - dst += dst_skip; - continue; - } - const RGBA32* sl = source.scanline(sr); - for (int x = x_start; x < clipped_rect.width() + x_start; ++x) { - int sx = x - offset.x(); - if (sx < source.size().width() && sx >= 0) - dst[x - x_start] = sl[sx]; - } - dst += dst_skip; - } - return; - } - - ASSERT_NOT_REACHED(); -} - -void Painter::blit_with_alpha(const Point& position, const Gfx::Bitmap& source, const Rect& src_rect) -{ - ASSERT(source.has_alpha_channel()); - Rect safe_src_rect = src_rect.intersected(source.rect()); - auto dst_rect = Rect(position, safe_src_rect.size()).translated(translation()); - auto clipped_rect = dst_rect.intersected(clip_rect()); - if (clipped_rect.is_empty()) - return; - const int first_row = clipped_rect.top() - dst_rect.top(); - const int last_row = clipped_rect.bottom() - dst_rect.top(); - const int first_column = clipped_rect.left() - dst_rect.left(); - const int last_column = clipped_rect.right() - dst_rect.left(); - RGBA32* dst = m_target->scanline(clipped_rect.y()) + clipped_rect.x(); - const RGBA32* src = source.scanline(src_rect.top() + first_row) + src_rect.left() + first_column; - const size_t dst_skip = m_target->pitch() / sizeof(RGBA32); - const size_t src_skip = source.pitch() / sizeof(RGBA32); - - for (int row = first_row; row <= last_row; ++row) { - for (int x = 0; x <= (last_column - first_column); ++x) { - u8 alpha = Color::from_rgba(src[x]).alpha(); - if (alpha == 0xff) - dst[x] = src[x]; - else if (!alpha) - continue; - else - dst[x] = Color::from_rgba(dst[x]).blend(Color::from_rgba(src[x])).value(); - } - dst += dst_skip; - src += src_skip; - } -} - -void Painter::blit(const Point& position, const Gfx::Bitmap& source, const Rect& src_rect, float opacity) -{ - if (opacity < 1.0f) - return blit_with_opacity(position, source, src_rect, opacity); - if (source.has_alpha_channel()) - return blit_with_alpha(position, source, src_rect); - auto safe_src_rect = src_rect.intersected(source.rect()); - ASSERT(source.rect().contains(safe_src_rect)); - auto dst_rect = Rect(position, safe_src_rect.size()).translated(translation()); - auto clipped_rect = dst_rect.intersected(clip_rect()); - if (clipped_rect.is_empty()) - return; - const int first_row = clipped_rect.top() - dst_rect.top(); - const int last_row = clipped_rect.bottom() - dst_rect.top(); - const int first_column = clipped_rect.left() - dst_rect.left(); - RGBA32* dst = m_target->scanline(clipped_rect.y()) + clipped_rect.x(); - const size_t dst_skip = m_target->pitch() / sizeof(RGBA32); - - if (source.format() == Bitmap::Format::RGB32 || source.format() == Bitmap::Format::RGBA32) { - const RGBA32* src = source.scanline(src_rect.top() + first_row) + src_rect.left() + first_column; - const size_t src_skip = source.pitch() / sizeof(RGBA32); - for (int row = first_row; row <= last_row; ++row) { - fast_u32_copy(dst, src, clipped_rect.width()); - dst += dst_skip; - src += src_skip; - } - return; - } - - if (source.format() == Bitmap::Format::Indexed8) { - const u8* src = source.bits(src_rect.top() + first_row) + src_rect.left() + first_column; - const size_t src_skip = source.pitch(); - for (int row = first_row; row <= last_row; ++row) { - for (int i = 0; i < clipped_rect.width(); ++i) - dst[i] = source.palette_color(src[i]).value(); - dst += dst_skip; - src += src_skip; - } - return; - } - - ASSERT_NOT_REACHED(); -} - -template<bool has_alpha_channel, typename GetPixel> -ALWAYS_INLINE static void do_draw_integer_scaled_bitmap(Gfx::Bitmap& target, const Rect& dst_rect, const Gfx::Bitmap& source, int hfactor, int vfactor, GetPixel get_pixel) -{ - for (int y = source.rect().top(); y <= source.rect().bottom(); ++y) { - int dst_y = dst_rect.y() + y * vfactor; - for (int x = source.rect().left(); x <= source.rect().right(); ++x) { - auto src_pixel = get_pixel(source, x, y); - for (int yo = 0; yo < vfactor; ++yo) { - auto* scanline = (Color*)target.scanline(dst_y + yo); - int dst_x = dst_rect.x() + x * hfactor; - for (int xo = 0; xo < hfactor; ++xo) { - if constexpr (has_alpha_channel) - scanline[dst_x + xo] = scanline[dst_x + xo].blend(src_pixel); - else - scanline[dst_x + xo] = src_pixel; - } - } - } - } -} - -template<bool has_alpha_channel, typename GetPixel> -ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, const Rect& dst_rect, const Rect& clipped_rect, const Gfx::Bitmap& source, const Rect& src_rect, int hscale, int vscale, GetPixel get_pixel) -{ - if (dst_rect == clipped_rect && !(dst_rect.width() % src_rect.width()) && !(dst_rect.height() % src_rect.height())) { - int hfactor = dst_rect.width() / src_rect.width(); - int vfactor = dst_rect.height() / src_rect.height(); - if (hfactor == 2 && vfactor == 2) - return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, source, 2, 2, get_pixel); - if (hfactor == 3 && vfactor == 3) - return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, source, 3, 3, get_pixel); - if (hfactor == 4 && vfactor == 4) - return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, source, 4, 4, get_pixel); - return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, source, hfactor, vfactor, get_pixel); - } - - for (int y = clipped_rect.top(); y <= clipped_rect.bottom(); ++y) { - auto* scanline = (Color*)target.scanline(y); - for (int x = clipped_rect.left(); x <= clipped_rect.right(); ++x) { - auto scaled_x = ((x - dst_rect.x()) * hscale) >> 16; - auto scaled_y = ((y - dst_rect.y()) * vscale) >> 16; - auto src_pixel = get_pixel(source, scaled_x, scaled_y); - - if constexpr (has_alpha_channel) { - scanline[x] = scanline[x].blend(src_pixel); - } else - scanline[x] = src_pixel; - } - } -} - -void Painter::draw_scaled_bitmap(const Rect& a_dst_rect, const Gfx::Bitmap& source, const Rect& src_rect) -{ - auto dst_rect = a_dst_rect; - if (dst_rect.size() == src_rect.size()) - return blit(dst_rect.location(), source, src_rect); - - auto safe_src_rect = src_rect.intersected(source.rect()); - ASSERT(source.rect().contains(safe_src_rect)); - dst_rect.move_by(state().translation); - auto clipped_rect = dst_rect.intersected(clip_rect()); - if (clipped_rect.is_empty()) - return; - - int hscale = (src_rect.width() << 16) / dst_rect.width(); - int vscale = (src_rect.height() << 16) / dst_rect.height(); - - if (source.has_alpha_channel()) { - switch (source.format()) { - case Bitmap::Format::RGB32: - do_draw_scaled_bitmap<true>(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel<Bitmap::Format::RGB32>); - break; - case Bitmap::Format::RGBA32: - do_draw_scaled_bitmap<true>(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel<Bitmap::Format::RGBA32>); - break; - case Bitmap::Format::Indexed8: - do_draw_scaled_bitmap<true>(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel<Bitmap::Format::Indexed8>); - break; - default: - do_draw_scaled_bitmap<true>(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel<Bitmap::Format::Invalid>); - break; - } - } else { - switch (source.format()) { - case Bitmap::Format::RGB32: - do_draw_scaled_bitmap<false>(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel<Bitmap::Format::RGB32>); - break; - case Bitmap::Format::RGBA32: - do_draw_scaled_bitmap<false>(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel<Bitmap::Format::RGBA32>); - break; - case Bitmap::Format::Indexed8: - do_draw_scaled_bitmap<false>(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel<Bitmap::Format::Indexed8>); - break; - default: - do_draw_scaled_bitmap<false>(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel<Bitmap::Format::Invalid>); - break; - } - } -} - -[[gnu::flatten]] void Painter::draw_glyph(const Point& point, char ch, Color color) -{ - draw_glyph(point, ch, font(), color); -} - -[[gnu::flatten]] void Painter::draw_glyph(const Point& point, char ch, const Font& font, Color color) -{ - draw_bitmap(point, font.glyph_bitmap(ch), color); -} - -void Painter::draw_emoji(const Point& point, const Gfx::Bitmap& emoji, const Font& font) -{ - if (!font.is_fixed_width()) - blit(point, emoji, emoji.rect()); - else { - Rect dst_rect { - point.x(), - point.y(), - font.glyph_width('x'), - font.glyph_height() - }; - draw_scaled_bitmap(dst_rect, emoji, emoji.rect()); - } -} - -void Painter::draw_glyph_or_emoji(const Point& point, u32 codepoint, const Font& font, Color color) -{ - if (codepoint < 256) { - // This looks like a regular character. - draw_glyph(point, (char)codepoint, font, color); - return; - } - - // Perhaps it's an emoji? - auto* emoji = Emoji::emoji_for_codepoint(codepoint); - if (emoji == nullptr) { -#ifdef EMOJI_DEBUG - dbg() << "Failed to find an emoji for codepoint " << codepoint; -#endif - draw_glyph(point, '?', font, color); - return; - } - - draw_emoji(point, *emoji, font); -} - -void Painter::draw_text_line(const Rect& a_rect, const Utf8View& text, const Font& font, TextAlignment alignment, Color color, TextElision elision) -{ - auto rect = a_rect; - Utf8View final_text(text); - String elided_text; - if (elision == TextElision::Right) { - int text_width = font.width(final_text); - if (font.width(final_text) > rect.width()) { - int glyph_spacing = font.glyph_spacing(); - int byte_offset = 0; - int new_width = font.width("..."); - if (new_width < text_width) { - for (auto it = final_text.begin(); it != final_text.end(); ++it) { - u32 codepoint = *it; - int glyph_width = font.glyph_or_emoji_width(codepoint); - // NOTE: Glyph spacing should not be added after the last glyph on the line, - // but since we are here because the last glyph does not actually fit on the line, - // we don't have to worry about spacing. - int width_with_this_glyph_included = new_width + glyph_width + glyph_spacing; - if (width_with_this_glyph_included > rect.width()) - break; - byte_offset = final_text.byte_offset_of(it); - new_width += glyph_width + glyph_spacing; - } - StringBuilder builder; - builder.append(final_text.substring_view(0, byte_offset).as_string()); - builder.append("..."); - elided_text = builder.to_string(); - final_text = Utf8View { elided_text }; - } - } - } - - switch (alignment) { - case TextAlignment::TopLeft: - case TextAlignment::CenterLeft: - break; - case TextAlignment::TopRight: - case TextAlignment::CenterRight: - rect.set_x(rect.right() - font.width(final_text)); - break; - case TextAlignment::Center: { - auto shrunken_rect = rect; - shrunken_rect.set_width(font.width(final_text)); - shrunken_rect.center_within(rect); - rect = shrunken_rect; - break; - } - default: - ASSERT_NOT_REACHED(); - } - - auto point = rect.location(); - int space_width = font.glyph_width(' ') + font.glyph_spacing(); - - for (u32 codepoint : final_text) { - if (codepoint == ' ') { - point.move_by(space_width, 0); - continue; - } - draw_glyph_or_emoji(point, codepoint, font, color); - point.move_by(font.glyph_or_emoji_width(codepoint) + font.glyph_spacing(), 0); - } -} - -void Painter::draw_text(const Rect& rect, const StringView& text, TextAlignment alignment, Color color, TextElision elision) -{ - draw_text(rect, text, font(), alignment, color, elision); -} - -void Painter::draw_text(const Rect& rect, const StringView& raw_text, const Font& font, TextAlignment alignment, Color color, TextElision elision) -{ - Utf8View text { raw_text }; - Vector<Utf8View, 32> lines; - - int start_of_current_line = 0; - for (auto it = text.begin(); it != text.end(); ++it) { - u32 codepoint = *it; - if (codepoint == '\n') { - int byte_offset = text.byte_offset_of(it); - Utf8View line = text.substring_view(start_of_current_line, byte_offset - start_of_current_line); - lines.append(line); - start_of_current_line = byte_offset + 1; - } - } - - if (start_of_current_line != text.byte_length()) { - Utf8View line = text.substring_view(start_of_current_line, text.byte_length() - start_of_current_line); - lines.append(line); - } - - static const int line_spacing = 4; - int line_height = font.glyph_height() + line_spacing; - Rect bounding_rect { 0, 0, 0, (lines.size() * line_height) - line_spacing }; - - for (auto& line : lines) { - auto line_width = font.width(line); - if (line_width > bounding_rect.width()) - bounding_rect.set_width(line_width); - } - - switch (alignment) { - case TextAlignment::TopLeft: - bounding_rect.set_location(rect.location()); - break; - case TextAlignment::TopRight: - bounding_rect.set_location({ (rect.right() + 1) - bounding_rect.width(), rect.y() }); - break; - case TextAlignment::CenterLeft: - bounding_rect.set_location({ rect.x(), rect.center().y() - (bounding_rect.height() / 2) }); - break; - case TextAlignment::CenterRight: - bounding_rect.set_location({ (rect.right() + 1) - bounding_rect.width(), rect.center().y() - (bounding_rect.height() / 2) }); - break; - case TextAlignment::Center: - bounding_rect.center_within(rect); - break; - default: - ASSERT_NOT_REACHED(); - } - - for (int i = 0; i < lines.size(); ++i) { - auto& line = lines[i]; - Rect line_rect { bounding_rect.x(), bounding_rect.y() + i * line_height, bounding_rect.width(), line_height }; - line_rect.intersect(rect); - draw_text_line(line_rect, line, font, alignment, color, elision); - } -} - -void Painter::set_pixel(const Point& p, Color color) -{ - auto point = p; - point.move_by(state().translation); - if (!clip_rect().contains(point)) - return; - m_target->scanline(point.y())[point.x()] = color.value(); -} - -[[gnu::always_inline]] inline void Painter::set_pixel_with_draw_op(u32& pixel, const Color& color) -{ - if (draw_op() == DrawOp::Copy) - pixel = color.value(); - else if (draw_op() == DrawOp::Xor) - pixel ^= color.value(); -} - -void Painter::draw_pixel(const Point& position, Color color, int thickness) -{ - ASSERT(draw_op() == DrawOp::Copy); - if (thickness == 1) - return set_pixel_with_draw_op(m_target->scanline(position.y())[position.x()], color); - Rect rect { position.translated(-(thickness / 2), -(thickness / 2)), { thickness, thickness } }; - fill_rect(rect.translated(-state().translation), color); -} - -void Painter::draw_line(const Point& p1, const Point& p2, Color color, int thickness, bool dotted) -{ - auto clip_rect = this->clip_rect(); - - auto point1 = p1; - point1.move_by(state().translation); - - auto point2 = p2; - point2.move_by(state().translation); - - // Special case: vertical line. - if (point1.x() == point2.x()) { - const int x = point1.x(); - if (x < clip_rect.left() || x > clip_rect.right()) - return; - if (point1.y() > point2.y()) - swap(point1, point2); - if (point1.y() > clip_rect.bottom()) - return; - if (point2.y() < clip_rect.top()) - return; - int min_y = max(point1.y(), clip_rect.top()); - int max_y = min(point2.y(), clip_rect.bottom()); - if (dotted) { - for (int y = min_y; y <= max_y; y += 2) - draw_pixel({ x, y }, color, thickness); - } else { - for (int y = min_y; y <= max_y; ++y) - draw_pixel({ x, y }, color, thickness); - } - return; - } - - // Special case: horizontal line. - if (point1.y() == point2.y()) { - const int y = point1.y(); - if (y < clip_rect.top() || y > clip_rect.bottom()) - return; - if (point1.x() > point2.x()) - swap(point1, point2); - if (point1.x() > clip_rect.right()) - return; - if (point2.x() < clip_rect.left()) - return; - int min_x = max(point1.x(), clip_rect.left()); - int max_x = min(point2.x(), clip_rect.right()); - if (dotted) { - for (int x = min_x; x <= max_x; x += 2) - draw_pixel({ x, y }, color, thickness); - } else { - for (int x = min_x; x <= max_x; ++x) - draw_pixel({ x, y }, color, thickness); - } - return; - } - - // FIXME: Implement dotted diagonal lines. - ASSERT(!dotted); - - const double adx = abs(point2.x() - point1.x()); - const double ady = abs(point2.y() - point1.y()); - - if (adx > ady) { - if (point1.x() > point2.x()) - swap(point1, point2); - } else { - if (point1.y() > point2.y()) - swap(point1, point2); - } - - // FIXME: Implement clipping below. - const double dx = point2.x() - point1.x(); - const double dy = point2.y() - point1.y(); - double error = 0; - - if (dx > dy) { - const double y_step = dy == 0 ? 0 : (dy > 0 ? 1 : -1); - const double delta_error = fabs(dy / dx); - int y = point1.y(); - for (int x = point1.x(); x <= point2.x(); ++x) { - if (clip_rect.contains(x, y)) - draw_pixel({ x, y }, color, thickness); - error += delta_error; - if (error >= 0.5) { - y = (double)y + y_step; - error -= 1.0; - } - } - } else { - const double x_step = dx == 0 ? 0 : (dx > 0 ? 1 : -1); - const double delta_error = fabs(dx / dy); - int x = point1.x(); - for (int y = point1.y(); y <= point2.y(); ++y) { - if (clip_rect.contains(x, y)) - draw_pixel({ x, y }, color, thickness); - error += delta_error; - if (error >= 0.5) { - x = (double)x + x_step; - error -= 1.0; - } - } - } -} - -void Painter::add_clip_rect(const Rect& rect) -{ - state().clip_rect.intersect(rect.translated(m_clip_origin.location())); - state().clip_rect.intersect(m_target->rect()); -} - -void Painter::clear_clip_rect() -{ - state().clip_rect = m_clip_origin; -} - -PainterStateSaver::PainterStateSaver(Painter& painter) - : m_painter(painter) -{ - m_painter.save(); -} - -PainterStateSaver::~PainterStateSaver() -{ - m_painter.restore(); -} - -} diff --git a/Libraries/LibDraw/Painter.h b/Libraries/LibDraw/Painter.h deleted file mode 100644 index 638ef9d30e..0000000000 --- a/Libraries/LibDraw/Painter.h +++ /dev/null @@ -1,133 +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 "Color.h" -#include "Point.h" -#include "Rect.h" -#include "Size.h" -#include <AK/String.h> -#include <AK/Utf8View.h> -#include <LibDraw/TextAlignment.h> -#include <LibDraw/TextElision.h> - -namespace Gfx { - -class CharacterBitmap; -class GlyphBitmap; -class Bitmap; -class Font; -class Emoji; - -class Painter { -public: - explicit Painter(Gfx::Bitmap&); - ~Painter(); - void clear_rect(const Rect&, Color); - void fill_rect(const Rect&, Color); - void fill_rect_with_gradient(const Rect&, Color gradient_start, Color gradient_end); - void draw_rect(const Rect&, Color, bool rough = false); - void draw_bitmap(const Point&, const CharacterBitmap&, Color = Color()); - void draw_bitmap(const Point&, const GlyphBitmap&, Color = Color()); - void draw_ellipse_intersecting(const Rect&, Color, int thickness = 1); - void set_pixel(const Point&, Color); - void draw_line(const Point&, const Point&, Color, int thickness = 1, bool dotted = false); - void draw_scaled_bitmap(const Rect& dst_rect, const Gfx::Bitmap&, const Rect& src_rect); - void blit(const Point&, const Gfx::Bitmap&, const Rect& src_rect, float opacity = 1.0f); - void blit_dimmed(const Point&, const Gfx::Bitmap&, const Rect& src_rect); - void draw_tiled_bitmap(const Rect& dst_rect, const Gfx::Bitmap&); - void blit_offset(const Point&, const Gfx::Bitmap&, const Rect& src_rect, const Point&); - void blit_scaled(const Rect&, const Gfx::Bitmap&, const Rect&, float, float); - void draw_text(const Rect&, const StringView&, const Font&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None); - void draw_text(const Rect&, const StringView&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None); - void draw_glyph(const Point&, char, Color); - void draw_glyph(const Point&, char, const Font&, Color); - void draw_emoji(const Point&, const Gfx::Bitmap&, const Font&); - void draw_glyph_or_emoji(const Point&, u32 codepoint, const Font&, Color); - - const Font& font() const { return *state().font; } - void set_font(const Font& font) { state().font = &font; } - - enum class DrawOp { - Copy, - Xor - }; - void set_draw_op(DrawOp op) { state().draw_op = op; } - DrawOp draw_op() const { return state().draw_op; } - - void add_clip_rect(const Rect& rect); - void clear_clip_rect(); - Rect clip_rect() const { return state().clip_rect; } - - void translate(int dx, int dy) { state().translation.move_by(dx, dy); } - void translate(const Point& delta) { state().translation.move_by(delta); } - - Point translation() const { return state().translation; } - - Gfx::Bitmap* target() { return m_target.ptr(); } - - void save() { m_state_stack.append(m_state_stack.last()); } - void restore() - { - ASSERT(m_state_stack.size() > 1); - m_state_stack.take_last(); - } - -protected: - void set_pixel_with_draw_op(u32& pixel, const Color&); - void fill_rect_with_draw_op(const Rect&, Color); - void blit_with_alpha(const Point&, const Gfx::Bitmap&, const Rect& src_rect); - void blit_with_opacity(const Point&, const Gfx::Bitmap&, const Rect& src_rect, float opacity); - void draw_pixel(const Point&, Color, int thickness = 1); - - void draw_text_line(const Rect&, const Utf8View&, const Font&, TextAlignment, Color, TextElision); - - struct State { - const Font* font; - Point translation; - Rect clip_rect; - DrawOp draw_op; - }; - - State& state() { return m_state_stack.last(); } - const State& state() const { return m_state_stack.last(); } - - Rect m_clip_origin; - NonnullRefPtr<Gfx::Bitmap> m_target; - Vector<State, 4> m_state_stack; -}; - -class PainterStateSaver { -public: - explicit PainterStateSaver(Painter&); - ~PainterStateSaver(); - -private: - Painter& m_painter; -}; - -} diff --git a/Libraries/LibDraw/Palette.cpp b/Libraries/LibDraw/Palette.cpp deleted file mode 100644 index 217c1c9bcf..0000000000 --- a/Libraries/LibDraw/Palette.cpp +++ /dev/null @@ -1,76 +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. - */ - -#include <LibDraw/Palette.h> - -namespace Gfx { - -NonnullRefPtr<PaletteImpl> PaletteImpl::create_with_shared_buffer(SharedBuffer& buffer) -{ - return adopt(*new PaletteImpl(buffer)); -} - -PaletteImpl::PaletteImpl(SharedBuffer& buffer) - : m_theme_buffer(buffer) -{ -} - -Palette::Palette(const PaletteImpl& impl) - : m_impl(impl) -{ -} - -Palette::~Palette() -{ -} - -const SystemTheme& PaletteImpl::theme() const -{ - return *(const SystemTheme*)m_theme_buffer->data(); -} - -Color PaletteImpl::color(ColorRole role) const -{ - ASSERT((int)role < (int)ColorRole::__Count); - return theme().color[(int)role]; -} - -NonnullRefPtr<PaletteImpl> PaletteImpl::clone() const -{ - auto new_theme_buffer = SharedBuffer::create_with_size(m_theme_buffer->size()); - memcpy(new_theme_buffer->data(), m_theme_buffer->data(), m_theme_buffer->size()); - return adopt(*new PaletteImpl(*new_theme_buffer)); -} - -void Palette::set_color(ColorRole role, Color color) -{ - if (m_impl->ref_count() != 1) - m_impl = m_impl->clone(); - auto& theme = const_cast<SystemTheme&>(impl().theme()); - theme.color[(int)role] = color; -} - -} diff --git a/Libraries/LibDraw/Palette.h b/Libraries/LibDraw/Palette.h deleted file mode 100644 index 8e05f32b5a..0000000000 --- a/Libraries/LibDraw/Palette.h +++ /dev/null @@ -1,115 +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/Badge.h> -#include <AK/Noncopyable.h> -#include <LibDraw/SystemTheme.h> - -namespace GUI { -class Application; -} - -namespace Gfx { - -class PaletteImpl : public RefCounted<PaletteImpl> { - AK_MAKE_NONCOPYABLE(PaletteImpl) - AK_MAKE_NONMOVABLE(PaletteImpl) -public: - static NonnullRefPtr<PaletteImpl> create_with_shared_buffer(SharedBuffer&); - NonnullRefPtr<PaletteImpl> clone() const; - - Color color(ColorRole) const; - const SystemTheme& theme() const; - - void replace_internal_buffer(Badge<GUI::Application>, SharedBuffer& buffer) { m_theme_buffer = buffer; } - -private: - explicit PaletteImpl(SharedBuffer&); - - RefPtr<SharedBuffer> m_theme_buffer; -}; - -class Palette { - -public: - explicit Palette(const PaletteImpl&); - ~Palette(); - - Color window() const { return color(ColorRole::Window); } - Color window_text() const { return color(ColorRole::WindowText); } - Color selection() const { return color(ColorRole::Selection); } - Color selection_text() const { return color(ColorRole::SelectionText); } - Color desktop_background() const { return color(ColorRole::DesktopBackground); } - Color active_window_border1() const { return color(ColorRole::ActiveWindowBorder1); } - Color active_window_border2() const { return color(ColorRole::ActiveWindowBorder2); } - Color active_window_title() const { return color(ColorRole::ActiveWindowTitle); } - Color inactive_window_border1() const { return color(ColorRole::InactiveWindowBorder1); } - Color inactive_window_border2() const { return color(ColorRole::InactiveWindowBorder2); } - Color inactive_window_title() const { return color(ColorRole::InactiveWindowTitle); } - Color moving_window_border1() const { return color(ColorRole::MovingWindowBorder1); } - Color moving_window_border2() const { return color(ColorRole::MovingWindowBorder2); } - Color moving_window_title() const { return color(ColorRole::MovingWindowTitle); } - Color highlight_window_border1() const { return color(ColorRole::HighlightWindowBorder1); } - Color highlight_window_border2() const { return color(ColorRole::HighlightWindowBorder2); } - Color highlight_window_title() const { return color(ColorRole::HighlightWindowTitle); } - Color menu_stripe() const { return color(ColorRole::MenuStripe); } - Color menu_base() const { return color(ColorRole::MenuBase); } - Color menu_base_text() const { return color(ColorRole::MenuBaseText); } - Color menu_selection() const { return color(ColorRole::MenuSelection); } - Color menu_selection_text() const { return color(ColorRole::MenuSelectionText); } - Color base() const { return color(ColorRole::Base); } - Color base_text() const { return color(ColorRole::BaseText); } - Color button() const { return color(ColorRole::Button); } - Color button_text() const { return color(ColorRole::ButtonText); } - Color threed_highlight() const { return color(ColorRole::ThreedHighlight); } - Color threed_shadow1() const { return color(ColorRole::ThreedShadow1); } - Color threed_shadow2() const { return color(ColorRole::ThreedShadow2); } - Color hover_highlight() const { return color(ColorRole::ThreedHighlight); } - Color rubber_band_fill() const { return color(ColorRole::RubberBandFill); } - Color rubber_band_border() const { return color(ColorRole::RubberBandBorder); } - - Color link() const { return color(ColorRole::Link); } - Color active_link() const { return color(ColorRole::ActiveLink); } - Color visited_link() const { return color(ColorRole::VisitedLink); } - - Color color(ColorRole role) const { return m_impl->color(role); } - - void set_color(ColorRole, Color); - - const SystemTheme& theme() const { return m_impl->theme(); } - - PaletteImpl& impl() { return *m_impl; } - const PaletteImpl& impl() const { return *m_impl; } - -private: - NonnullRefPtr<PaletteImpl> m_impl; -}; - -} - -using Gfx::Palette; diff --git a/Libraries/LibDraw/Point.h b/Libraries/LibDraw/Point.h deleted file mode 100644 index 8bdd76efbd..0000000000 --- a/Libraries/LibDraw/Point.h +++ /dev/null @@ -1,166 +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 <LibDraw/Orientation.h> - -namespace Gfx { - -class Rect; - -class Point { -public: - Point() {} - Point(int x, int y) - : m_x(x) - , m_y(y) - { - } - - int x() const { return m_x; } - int y() const { return m_y; } - - void set_x(int x) { m_x = x; } - void set_y(int y) { m_y = y; } - - void move_by(int dx, int dy) - { - m_x += dx; - m_y += dy; - } - - void move_by(const Point& delta) - { - move_by(delta.x(), delta.y()); - } - - Point translated(const Point& delta) const - { - Point point = *this; - point.move_by(delta); - return point; - } - - Point translated(int dx, int dy) const - { - Point point = *this; - point.move_by(dx, dy); - return point; - } - - void constrain(const Rect&); - - bool operator==(const Point& other) const - { - return m_x == other.m_x - && m_y == other.m_y; - } - - bool operator!=(const Point& other) const - { - return !(*this == other); - } - - Point operator-() const { return { -m_x, -m_y }; } - - Point operator-(const Point& other) const { return { m_x - other.m_x, m_y - other.m_y }; } - Point& operator-=(const Point& other) - { - m_x -= other.m_x; - m_y -= other.m_y; - return *this; - } - - Point& operator+=(const Point& other) - { - m_x += other.m_x; - m_y += other.m_y; - return *this; - } - Point operator+(const Point& other) const { return { m_x + other.m_x, m_y + other.m_y }; } - - String to_string() const { return String::format("[%d,%d]", x(), y()); } - - bool is_null() const { return !m_x && !m_y; } - - int primary_offset_for_orientation(Orientation orientation) const - { - return orientation == Orientation::Vertical ? y() : x(); - } - - void set_primary_offset_for_orientation(Orientation orientation, int value) - { - if (orientation == Orientation::Vertical) - set_y(value); - else - set_x(value); - } - - int secondary_offset_for_orientation(Orientation orientation) const - { - return orientation == Orientation::Vertical ? x() : y(); - } - - void set_secondary_offset_for_orientation(Orientation orientation, int value) - { - if (orientation == Orientation::Vertical) - set_x(value); - else - set_y(value); - } - - int dx_relative_to(const Point& other) const - { - return x() - other.x(); - } - - int dy_relative_to(const Point& other) const - { - return y() - other.y(); - } - - // Returns pixels moved from other in either direction - int pixels_moved(const Point& other) const - { - return max(abs(dx_relative_to(other)), abs(dy_relative_to(other))); - } - -private: - int m_x { 0 }; - int m_y { 0 }; -}; - -inline const LogStream& operator<<(const LogStream& stream, const Point& value) -{ - return stream << value.to_string(); -} - -} - -using Gfx::Point; diff --git a/Libraries/LibDraw/Rect.cpp b/Libraries/LibDraw/Rect.cpp deleted file mode 100644 index 45b47a1549..0000000000 --- a/Libraries/LibDraw/Rect.cpp +++ /dev/null @@ -1,128 +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. - */ - -#include "Rect.h" -#include <AK/StdLibExtras.h> - -void Rect::intersect(const Rect& 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); -} - -Rect Rect::united(const Rect& other) const -{ - if (is_null()) - return other; - if (other.is_null()) - return *this; - Rect 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<Rect, 4> Rect::shatter(const Rect& hammer) const -{ - Vector<Rect, 4> pieces; - if (!intersects(hammer)) { - pieces.unchecked_append(*this); - return pieces; - } - Rect top_shard { - x(), - y(), - width(), - hammer.y() - y() - }; - Rect bottom_shard { - x(), - hammer.y() + hammer.height(), - width(), - (y() + height()) - (hammer.y() + hammer.height()) - }; - Rect left_shard { - x(), - max(hammer.y(), y()), - hammer.x() - x(), - min((hammer.y() + hammer.height()), (y() + height())) - max(hammer.y(), y()) - }; - Rect 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 (intersects(top_shard)) - pieces.unchecked_append(top_shard); - if (intersects(bottom_shard)) - pieces.unchecked_append(bottom_shard); - if (intersects(left_shard)) - pieces.unchecked_append(left_shard); - if (intersects(right_shard)) - pieces.unchecked_append(right_shard); - - return pieces; -} - -void Rect::align_within(const Rect& 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/LibDraw/Rect.h b/Libraries/LibDraw/Rect.h deleted file mode 100644 index 3e9a1d8bfc..0000000000 --- a/Libraries/LibDraw/Rect.h +++ /dev/null @@ -1,337 +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 <LibDraw/Orientation.h> -#include <LibDraw/Point.h> -#include <LibDraw/Size.h> -#include <LibDraw/TextAlignment.h> - -namespace Gfx { - -class Rect { -public: - Rect() {} - Rect(int x, int y, int width, int height) - : m_location(x, y) - , m_size(width, height) - { - } - Rect(const Point& location, const Size& size) - : m_location(location) - , m_size(size) - { - } - - bool is_null() const - { - return width() == 0 && height() == 0; - } - - bool is_empty() const - { - return width() <= 0 || height() <= 0; - } - - void move_by(int dx, int dy) - { - m_location.move_by(dx, dy); - } - - void move_by(const Point& delta) - { - m_location.move_by(delta); - } - - Point center() const - { - return { x() + width() / 2, y() + height() / 2 }; - } - - void set_location(const Point& location) - { - m_location = location; - } - - void set_size(const Size& size) - { - m_size = size; - } - - void set_size(int width, int height) - { - m_size.set_width(width); - m_size.set_height(height); - } - - void inflate(int w, int h) - { - set_x(x() - w / 2); - set_width(width() + w); - set_y(y() - h / 2); - set_height(height() + h); - } - - void shrink(int w, int h) - { - set_x(x() + w / 2); - set_width(width() - w); - set_y(y() + h / 2); - set_height(height() - h); - } - - Rect shrunken(int w, int h) const - { - Rect rect = *this; - rect.shrink(w, h); - return rect; - } - - Rect inflated(int w, int h) const - { - Rect rect = *this; - rect.inflate(w, h); - return rect; - } - - Rect translated(int dx, int dy) const - { - Rect rect = *this; - rect.move_by(dx, dy); - return rect; - } - - Rect translated(const Point& delta) const - { - Rect rect = *this; - rect.move_by(delta); - return rect; - } - - bool contains_vertically(int y) const - { - return y >= top() && y <= bottom(); - } - - bool contains_horizontally(int x) const - { - return x >= left() && x <= right(); - } - - bool contains(int x, int y) const - { - return x >= m_location.x() && x <= right() && y >= m_location.y() && y <= bottom(); - } - - bool contains(const Point& point) const - { - return contains(point.x(), point.y()); - } - - bool contains(const Rect& other) const - { - return left() <= other.left() - && right() >= other.right() - && top() <= other.top() - && bottom() >= other.bottom(); - } - - int primary_offset_for_orientation(Orientation orientation) const { return m_location.primary_offset_for_orientation(orientation); } - void set_primary_offset_for_orientation(Orientation orientation, int value) { m_location.set_primary_offset_for_orientation(orientation, value); } - int secondary_offset_for_orientation(Orientation orientation) const { return m_location.secondary_offset_for_orientation(orientation); } - void set_secondary_offset_for_orientation(Orientation orientation, int value) { m_location.set_secondary_offset_for_orientation(orientation, value); } - - int primary_size_for_orientation(Orientation orientation) const { return m_size.primary_size_for_orientation(orientation); } - int secondary_size_for_orientation(Orientation orientation) const { return m_size.secondary_size_for_orientation(orientation); } - 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 - { - if (orientation == Orientation::Vertical) - return top(); - return left(); - } - - int 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; } - - void set_left(int left) - { - set_x(left); - } - - void set_top(int top) - { - set_y(top); - } - - void set_right(int right) - { - set_width(right - x() + 1); - } - - void set_bottom(int bottom) - { - set_height(bottom - y() + 1); - } - - void set_right_without_resize(int new_right) - { - int delta = new_right - right(); - move_by(delta, 0); - } - - void set_bottom_without_resize(int new_bottom) - { - int delta = new_bottom - bottom(); - move_by(0, delta); - } - - bool intersects_vertically(const Rect& other) const - { - return top() <= other.bottom() - && other.top() <= bottom(); - } - - bool intersects_horizontally(const Rect& other) const - { - return left() <= other.right() - && other.left() <= right(); - } - - bool intersects(const Rect& other) const - { - return left() <= other.right() - && other.left() <= right() - && top() <= other.bottom() - && 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(); } - - 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); } - - Point location() const { return m_location; } - Size size() const { return m_size; } - - Vector<Rect, 4> shatter(const Rect& hammer) const; - - bool operator==(const Rect& other) const - { - return m_location == other.m_location - && m_size == other.m_size; - } - - void intersect(const Rect&); - - static Rect from_two_points(const Point& a, const Point& b) - { - return { min(a.x(), b.x()), min(a.y(), b.y()), abs(a.x() - b.x()), abs(a.y() - b.y()) }; - } - - static Rect intersection(const Rect& a, const Rect& b) - { - Rect r(a); - r.intersect(b); - return r; - } - - Rect intersected(const Rect& other) const - { - return intersection(*this, other); - } - - Rect united(const Rect&) const; - - Point top_left() const { return { left(), top() }; } - Point top_right() const { return { right(), top() }; } - Point bottom_left() const { return { left(), bottom() }; } - Point bottom_right() const { return { right(), bottom() }; } - - void align_within(const Rect&, TextAlignment); - - void center_within(const Rect& other) - { - center_horizontally_within(other); - center_vertically_within(other); - } - - void center_horizontally_within(const Rect& other) - { - set_x(other.center().x() - width() / 2); - } - - void center_vertically_within(const Rect& other) - { - set_y(other.center().y() - height() / 2); - } - - String to_string() const { return String::format("[%d,%d %dx%d]", x(), y(), width(), height()); } - -private: - Point m_location; - Size m_size; -}; - -inline void Point::constrain(const Rect& 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 Rect& value) -{ - return stream << value.to_string(); -} - -} - -using Gfx::Rect; diff --git a/Libraries/LibDraw/Size.h b/Libraries/LibDraw/Size.h deleted file mode 100644 index bc027617ca..0000000000 --- a/Libraries/LibDraw/Size.h +++ /dev/null @@ -1,119 +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 <LibDraw/Orientation.h> - -namespace Gfx { - -class Size { -public: - Size() {} - Size(int w, int h) - : m_width(w) - , m_height(h) - { - } - - 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; } - - int area() const { return width() * height(); } - - void set_width(int w) { m_width = w; } - void set_height(int h) { m_height = h; } - - bool operator==(const Size& other) const - { - return m_width == other.m_width && m_height == other.m_height; - } - - bool operator!=(const Size& other) const - { - return !(*this == other); - } - - Size& operator-=(const Size& other) - { - m_width -= other.m_width; - m_height -= other.m_height; - return *this; - } - - Size& operator+=(const Size& other) - { - m_width += other.m_width; - m_height += other.m_height; - return *this; - } - - int primary_size_for_orientation(Orientation orientation) const - { - return orientation == Orientation::Vertical ? height() : width(); - } - - void set_primary_size_for_orientation(Orientation orientation, int value) - { - if (orientation == Orientation::Vertical) - set_height(value); - else - set_width(value); - } - - int secondary_size_for_orientation(Orientation orientation) const - { - return orientation == Orientation::Vertical ? width() : height(); - } - - void set_secondary_size_for_orientation(Orientation orientation, int value) - { - if (orientation == Orientation::Vertical) - set_width(value); - else - set_height(value); - } - - String to_string() const { return String::format("[%dx%d]", m_width, m_height); } - -private: - int m_width { 0 }; - int m_height { 0 }; -}; - -inline const LogStream& operator<<(const LogStream& stream, const Size& value) -{ - return stream << value.to_string(); -} - -} - -using Gfx::Size; diff --git a/Libraries/LibDraw/StylePainter.cpp b/Libraries/LibDraw/StylePainter.cpp deleted file mode 100644 index a94715c3dd..0000000000 --- a/Libraries/LibDraw/StylePainter.cpp +++ /dev/null @@ -1,315 +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. - */ - -#include <LibDraw/GraphicsBitmap.h> -#include <LibDraw/Painter.h> -#include <LibDraw/Palette.h> -#include <LibDraw/StylePainter.h> - -namespace Gfx { - -void StylePainter::paint_tab_button(Painter& painter, const Rect& rect, const Palette& palette, bool active, bool hovered, bool enabled) -{ - Color base_color = palette.button(); - Color highlight_color2 = palette.threed_highlight(); - Color shadow_color1 = palette.threed_shadow1(); - Color shadow_color2 = palette.threed_shadow2(); - - if (hovered && enabled && !active) - base_color = palette.hover_highlight(); - - PainterStateSaver saver(painter); - painter.translate(rect.location()); - - // Base - painter.fill_rect({ 1, 1, rect.width() - 2, rect.height() - 1 }, base_color); - - // Top line - painter.draw_line({ 2, 0 }, { rect.width() - 3, 0 }, highlight_color2); - - // Left side - painter.draw_line({ 0, 2 }, { 0, rect.height() - 1 }, highlight_color2); - painter.set_pixel({ 1, 1 }, highlight_color2); - - // Right side - painter.draw_line({ - rect.width() - 1, - 2, - }, - { rect.width() - 1, rect.height() - 1 }, shadow_color2); - painter.draw_line({ - rect.width() - 2, - 2, - }, - { rect.width() - 2, rect.height() - 1 }, shadow_color1); - painter.set_pixel({ - rect.width() - 2, - 1, - }, - shadow_color2); -} - -static void paint_button_new(Painter& painter, const Rect& rect, const Palette& palette, bool pressed, bool checked, bool hovered, bool enabled) -{ - Color button_color = palette.button(); - Color highlight_color2 = palette.threed_highlight(); - Color shadow_color1 = palette.threed_shadow1(); - Color shadow_color2 = palette.threed_shadow2(); - - if (checked && enabled) { - if (hovered) - button_color = palette.hover_highlight(); - else - button_color = palette.button(); - } else if (hovered && enabled) - button_color = palette.hover_highlight(); - - PainterStateSaver saver(painter); - painter.translate(rect.location()); - - if (pressed || checked) { - // Base - painter.fill_rect({ 1, 1, rect.width() - 2, rect.height() - 2 }, button_color); - - painter.draw_rect({ {}, rect.size() }, shadow_color2); - - // Sunken shadow - painter.draw_line({ 1, 1 }, { rect.width() - 2, 1 }, shadow_color1); - painter.draw_line({ 1, 2 }, { 1, rect.height() - 2 }, shadow_color1); - } else { - // Base - painter.fill_rect({ 1, 1, rect.width() - 3, rect.height() - 3 }, button_color); - - // Outer highlight - painter.draw_line({ 0, 0 }, { rect.width() - 2, 0 }, highlight_color2); - painter.draw_line({ 0, 1 }, { 0, rect.height() - 2 }, highlight_color2); - - // Outer shadow - painter.draw_line({ 0, rect.height() - 1 }, { rect.width() - 1, rect.height() - 1 }, shadow_color2); - painter.draw_line({ rect.width() - 1, 0 }, { rect.width() - 1, rect.height() - 2 }, shadow_color2); - - // Inner shadow - painter.draw_line({ 1, rect.height() - 2 }, { rect.width() - 2, rect.height() - 2 }, shadow_color1); - painter.draw_line({ rect.width() - 2, 1 }, { rect.width() - 2, rect.height() - 3 }, shadow_color1); - } -} - -void StylePainter::paint_button(Painter& painter, const Rect& rect, const Palette& palette, ButtonStyle button_style, bool pressed, bool hovered, bool checked, bool enabled) -{ - if (button_style == ButtonStyle::Normal) - return paint_button_new(painter, rect, palette, pressed, checked, hovered, enabled); - - Color button_color = palette.button(); - Color highlight_color = palette.threed_highlight(); - Color shadow_color = palette.threed_shadow1(); - - if (button_style == ButtonStyle::CoolBar && !enabled) - return; - - PainterStateSaver saver(painter); - painter.translate(rect.location()); - - if (pressed || checked) { - // Base - painter.fill_rect({ 1, 1, rect.width() - 2, rect.height() - 2 }, button_color); - - // Sunken shadow - painter.draw_line({ 1, 1 }, { rect.width() - 2, 1 }, shadow_color); - painter.draw_line({ 1, 2 }, { 1, rect.height() - 2 }, shadow_color); - - // Bottom highlight - painter.draw_line({ rect.width() - 2, 1 }, { rect.width() - 2, rect.height() - 3 }, highlight_color); - painter.draw_line({ 1, rect.height() - 2 }, { rect.width() - 2, rect.height() - 2 }, highlight_color); - } else if (button_style == ButtonStyle::CoolBar && hovered) { - // Base - painter.fill_rect({ 1, 1, rect.width() - 2, rect.height() - 2 }, button_color); - - // White highlight - painter.draw_line({ 1, 1 }, { rect.width() - 2, 1 }, highlight_color); - painter.draw_line({ 1, 2 }, { 1, rect.height() - 2 }, highlight_color); - - // Gray shadow - painter.draw_line({ rect.width() - 2, 1 }, { rect.width() - 2, rect.height() - 3 }, shadow_color); - painter.draw_line({ 1, rect.height() - 2 }, { rect.width() - 2, rect.height() - 2 }, shadow_color); - } -} - -void StylePainter::paint_surface(Painter& painter, const Rect& rect, const Palette& palette, bool paint_vertical_lines, bool paint_top_line) -{ - painter.fill_rect({ rect.x(), rect.y() + 1, rect.width(), rect.height() - 2 }, palette.button()); - painter.draw_line(rect.top_left(), rect.top_right(), paint_top_line ? palette.threed_highlight() : palette.button()); - painter.draw_line(rect.bottom_left(), rect.bottom_right(), palette.threed_shadow1()); - if (paint_vertical_lines) { - painter.draw_line(rect.top_left().translated(0, 1), rect.bottom_left().translated(0, -1), palette.threed_highlight()); - painter.draw_line(rect.top_right(), rect.bottom_right().translated(0, -1), palette.threed_shadow1()); - } -} - -void StylePainter::paint_frame(Painter& painter, const Rect& rect, const Palette& palette, FrameShape shape, FrameShadow shadow, int thickness, bool skip_vertical_lines) -{ - Color top_left_color; - Color bottom_right_color; - Color dark_shade = palette.threed_shadow1(); - Color light_shade = palette.threed_highlight(); - - if (shape == FrameShape::Container && thickness >= 2) { - if (shadow == FrameShadow::Raised) { - dark_shade = palette.threed_shadow2(); - } - } - - if (shadow == FrameShadow::Raised) { - top_left_color = light_shade; - bottom_right_color = dark_shade; - } else if (shadow == FrameShadow::Sunken) { - top_left_color = dark_shade; - bottom_right_color = light_shade; - } else if (shadow == FrameShadow::Plain) { - top_left_color = dark_shade; - bottom_right_color = dark_shade; - } - - if (thickness >= 1) { - painter.draw_line(rect.top_left(), rect.top_right(), top_left_color); - painter.draw_line(rect.bottom_left(), rect.bottom_right(), bottom_right_color); - - if (shape != FrameShape::Panel || !skip_vertical_lines) { - painter.draw_line(rect.top_left().translated(0, 1), rect.bottom_left().translated(0, -1), top_left_color); - painter.draw_line(rect.top_right(), rect.bottom_right().translated(0, -1), bottom_right_color); - } - } - - if (shape == FrameShape::Container && thickness >= 2) { - Color top_left_color; - Color bottom_right_color; - Color dark_shade = palette.threed_shadow2(); - Color light_shade = palette.button(); - if (shadow == FrameShadow::Raised) { - dark_shade = palette.threed_shadow1(); - top_left_color = light_shade; - bottom_right_color = dark_shade; - } else if (shadow == FrameShadow::Sunken) { - top_left_color = dark_shade; - bottom_right_color = light_shade; - } else if (shadow == FrameShadow::Plain) { - top_left_color = dark_shade; - bottom_right_color = dark_shade; - } - Rect inner_container_frame_rect = rect.shrunken(2, 2); - painter.draw_line(inner_container_frame_rect.top_left(), inner_container_frame_rect.top_right(), top_left_color); - painter.draw_line(inner_container_frame_rect.bottom_left(), inner_container_frame_rect.bottom_right(), bottom_right_color); - painter.draw_line(inner_container_frame_rect.top_left().translated(0, 1), inner_container_frame_rect.bottom_left().translated(0, -1), top_left_color); - painter.draw_line(inner_container_frame_rect.top_right(), inner_container_frame_rect.bottom_right().translated(0, -1), bottom_right_color); - } - - if (shape == FrameShape::Box && thickness >= 2) { - swap(top_left_color, bottom_right_color); - Rect inner_rect = rect.shrunken(2, 2); - painter.draw_line(inner_rect.top_left(), inner_rect.top_right(), top_left_color); - painter.draw_line(inner_rect.bottom_left(), inner_rect.bottom_right(), bottom_right_color); - painter.draw_line(inner_rect.top_left().translated(0, 1), inner_rect.bottom_left().translated(0, -1), top_left_color); - painter.draw_line(inner_rect.top_right(), inner_rect.bottom_right().translated(0, -1), bottom_right_color); - } -} - -void StylePainter::paint_window_frame(Painter& painter, const Rect& rect, const Palette& palette) -{ - Color base_color = palette.button(); - Color dark_shade = palette.threed_shadow2(); - Color mid_shade = palette.threed_shadow1(); - Color light_shade = palette.threed_highlight(); - - painter.draw_line(rect.top_left(), rect.top_right(), base_color); - painter.draw_line(rect.top_left().translated(0, 1), rect.bottom_left(), base_color); - painter.draw_line(rect.top_left().translated(1, 1), rect.top_right().translated(-1, 1), light_shade); - painter.draw_line(rect.top_left().translated(1, 1), rect.bottom_left().translated(1, -1), light_shade); - painter.draw_line(rect.top_left().translated(2, 2), rect.top_right().translated(-2, 2), base_color); - painter.draw_line(rect.top_left().translated(2, 2), rect.bottom_left().translated(2, -2), base_color); - - painter.draw_line(rect.top_right(), rect.bottom_right(), dark_shade); - painter.draw_line(rect.top_right().translated(-1, 1), rect.bottom_right().translated(-1, -1), mid_shade); - painter.draw_line(rect.top_right().translated(-2, 2), rect.bottom_right().translated(-2, -2), base_color); - painter.draw_line(rect.bottom_left(), rect.bottom_right(), dark_shade); - painter.draw_line(rect.bottom_left().translated(1, -1), rect.bottom_right().translated(-1, -1), mid_shade); - painter.draw_line(rect.bottom_left().translated(2, -2), rect.bottom_right().translated(-2, -2), base_color); -} - -void StylePainter::paint_progress_bar(Painter& painter, const Rect& rect, const Palette& palette, int min, int max, int value, const StringView& text) -{ - // First we fill the entire widget with the gradient. This incurs a bit of - // overdraw but ensures a consistent look throughout the progression. - Color start_color = palette.active_window_border1(); - Color end_color = palette.active_window_border2(); - painter.fill_rect_with_gradient(rect, start_color, end_color); - - if (!text.is_null()) { - painter.draw_text(rect.translated(1, 1), text, TextAlignment::Center, palette.base_text()); - painter.draw_text(rect, text, TextAlignment::Center, palette.base_text().inverted()); - } - - float range_size = max - min; - float progress = (value - min) / range_size; - - // Then we carve out a hole in the remaining part of the widget. - // We draw the text a third time, clipped and inverse, for sharp contrast. - float progress_width = progress * rect.width(); - Rect hole_rect { (int)progress_width, 0, (int)(rect.width() - progress_width), rect.height() }; - hole_rect.move_by(rect.location()); - hole_rect.set_right_without_resize(rect.right()); - PainterStateSaver saver(painter); - painter.fill_rect(hole_rect, palette.base()); - - painter.add_clip_rect(hole_rect); - if (!text.is_null()) - painter.draw_text(rect.translated(0, 0), text, TextAlignment::Center, palette.base_text()); -} - -static RefPtr<Gfx::Bitmap> s_unfilled_circle_bitmap; -static RefPtr<Gfx::Bitmap> s_filled_circle_bitmap; -static RefPtr<Gfx::Bitmap> s_changing_filled_circle_bitmap; -static RefPtr<Gfx::Bitmap> s_changing_unfilled_circle_bitmap; - -static const Gfx::Bitmap& circle_bitmap(bool checked, bool changing) -{ - if (changing) - return checked ? *s_changing_filled_circle_bitmap : *s_changing_unfilled_circle_bitmap; - return checked ? *s_filled_circle_bitmap : *s_unfilled_circle_bitmap; -} - -void StylePainter::paint_radio_button(Painter& painter, const Rect& rect, const Palette&, bool is_checked, bool is_being_pressed) -{ - if (!s_unfilled_circle_bitmap) { - s_unfilled_circle_bitmap = Bitmap::load_from_file("/res/icons/unfilled-radio-circle.png"); - s_filled_circle_bitmap = Bitmap::load_from_file("/res/icons/filled-radio-circle.png"); - s_changing_filled_circle_bitmap = Bitmap::load_from_file("/res/icons/changing-filled-radio-circle.png"); - s_changing_unfilled_circle_bitmap = Bitmap::load_from_file("/res/icons/changing-unfilled-radio-circle.png"); - } - - auto& bitmap = circle_bitmap(is_checked, is_being_pressed); - painter.blit(rect.location(), bitmap, bitmap.rect()); -} - -} diff --git a/Libraries/LibDraw/StylePainter.h b/Libraries/LibDraw/StylePainter.h deleted file mode 100644 index 9fd7d415e7..0000000000 --- a/Libraries/LibDraw/StylePainter.h +++ /dev/null @@ -1,66 +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 <LibDraw/Color.h> - -namespace Gfx { - -class Painter; -class Palette; -class Rect; - -enum class ButtonStyle { - Normal, - CoolBar -}; -enum class FrameShadow { - Plain, - Raised, - Sunken -}; -enum class FrameShape { - NoFrame, - Box, - Container, - Panel, - VerticalLine, - HorizontalLine -}; - -class StylePainter { -public: - static void paint_button(Painter&, const Rect&, const Palette&, ButtonStyle, bool pressed, bool hovered = false, bool checked = false, bool enabled = true); - static void paint_tab_button(Painter&, const Rect&, const Palette&, bool active, bool hovered, bool enabled); - static void paint_surface(Painter&, const Rect&, const Palette&, bool paint_vertical_lines = true, bool paint_top_line = true); - static void paint_frame(Painter&, const Rect&, const Palette&, FrameShape, FrameShadow, int thickness, bool skip_vertical_lines = false); - static void paint_window_frame(Painter&, const Rect&, const Palette&); - static void paint_progress_bar(Painter&, const Rect&, const Palette&, int min, int max, int value, const StringView& text = {}); - static void paint_radio_button(Painter&, const Rect&, const Palette&, bool is_checked, bool is_being_pressed); -}; - -} diff --git a/Libraries/LibDraw/SystemTheme.cpp b/Libraries/LibDraw/SystemTheme.cpp deleted file mode 100644 index 18b7922dfd..0000000000 --- a/Libraries/LibDraw/SystemTheme.cpp +++ /dev/null @@ -1,115 +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. - */ - -#include <LibCore/CConfigFile.h> -#include <LibDraw/SystemTheme.h> - -namespace Gfx { - -static SystemTheme dummy_theme; -static const SystemTheme* theme_page = &dummy_theme; -static RefPtr<SharedBuffer> theme_buffer; - -const SystemTheme& current_system_theme() -{ - ASSERT(theme_page); - return *theme_page; -} - -int current_system_theme_buffer_id() -{ - ASSERT(theme_buffer); - return theme_buffer->shared_buffer_id(); -} - -void set_system_theme(SharedBuffer& buffer) -{ - theme_buffer = buffer; - theme_page = (SystemTheme*)theme_buffer->data(); -} - -RefPtr<SharedBuffer> load_system_theme(const String& path) -{ - auto file = Core::ConfigFile::open(path); - auto buffer = SharedBuffer::create_with_size(sizeof(SystemTheme)); - - auto* data = (SystemTheme*)buffer->data(); - - auto get_color = [&](auto& name) { - auto color_string = file->read_entry("Colors", name); - auto color = Color::from_string(color_string); - if (!color.has_value()) - return Color(Color::Black); - return color.value(); - }; - -#define DO_COLOR(x) \ - data->color[(int)ColorRole::x] = get_color(#x) - - DO_COLOR(DesktopBackground); - DO_COLOR(ThreedHighlight); - DO_COLOR(ThreedShadow1); - DO_COLOR(ThreedShadow2); - DO_COLOR(HoverHighlight); - DO_COLOR(Selection); - DO_COLOR(SelectionText); - DO_COLOR(Window); - DO_COLOR(WindowText); - DO_COLOR(Base); - DO_COLOR(BaseText); - DO_COLOR(Button); - DO_COLOR(ButtonText); - DO_COLOR(DesktopBackground); - DO_COLOR(ActiveWindowBorder1); - DO_COLOR(ActiveWindowBorder2); - DO_COLOR(ActiveWindowTitle); - DO_COLOR(InactiveWindowBorder1); - DO_COLOR(InactiveWindowBorder2); - DO_COLOR(InactiveWindowTitle); - DO_COLOR(MovingWindowBorder1); - DO_COLOR(MovingWindowBorder2); - DO_COLOR(MovingWindowTitle); - DO_COLOR(HighlightWindowBorder1); - DO_COLOR(HighlightWindowBorder2); - DO_COLOR(HighlightWindowTitle); - DO_COLOR(MenuStripe); - DO_COLOR(MenuBase); - DO_COLOR(MenuBaseText); - DO_COLOR(MenuSelection); - DO_COLOR(MenuSelectionText); - DO_COLOR(RubberBandFill); - DO_COLOR(RubberBandBorder); - DO_COLOR(Link); - DO_COLOR(ActiveLink); - DO_COLOR(VisitedLink); - - buffer->seal(); - buffer->share_globally(); - - return buffer; -} - -} diff --git a/Libraries/LibDraw/SystemTheme.h b/Libraries/LibDraw/SystemTheme.h deleted file mode 100644 index a84afb92a1..0000000000 --- a/Libraries/LibDraw/SystemTheme.h +++ /dev/null @@ -1,90 +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/SharedBuffer.h> -#include <AK/Types.h> -#include <LibDraw/Color.h> - -namespace Gfx { - -enum class ColorRole { - NoRole, - DesktopBackground, - ActiveWindowBorder1, - ActiveWindowBorder2, - ActiveWindowTitle, - InactiveWindowBorder1, - InactiveWindowBorder2, - InactiveWindowTitle, - MovingWindowBorder1, - MovingWindowBorder2, - MovingWindowTitle, - HighlightWindowBorder1, - HighlightWindowBorder2, - HighlightWindowTitle, - MenuStripe, - MenuBase, - MenuBaseText, - MenuSelection, - MenuSelectionText, - Window, - WindowText, - Button, - ButtonText, - Base, - BaseText, - ThreedHighlight, - ThreedShadow1, - ThreedShadow2, - HoverHighlight, - Selection, - SelectionText, - RubberBandFill, - RubberBandBorder, - Link, - ActiveLink, - VisitedLink, - - __Count, - - Background = Window, - DisabledText = ThreedShadow1, -}; - -struct SystemTheme { - Color color[(int)ColorRole::__Count]; -}; - -const SystemTheme& current_system_theme(); -int current_system_theme_buffer_id(); -void set_system_theme(SharedBuffer&); -RefPtr<SharedBuffer> load_system_theme(const String& path); - -} - -using Gfx::ColorRole; diff --git a/Libraries/LibDraw/TextAlignment.h b/Libraries/LibDraw/TextAlignment.h deleted file mode 100644 index 4e527711b8..0000000000 --- a/Libraries/LibDraw/TextAlignment.h +++ /dev/null @@ -1,50 +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 - -namespace Gfx { - -enum class TextAlignment { - TopLeft, - CenterLeft, - Center, - CenterRight, - TopRight, -}; - -inline bool is_right_text_alignment(TextAlignment alignment) -{ - switch (alignment) { - case TextAlignment::CenterRight: - case TextAlignment::TopRight: - return true; - default: - return false; - } -} - -} diff --git a/Libraries/LibDraw/TextElision.h b/Libraries/LibDraw/TextElision.h deleted file mode 100644 index cf8cecc001..0000000000 --- a/Libraries/LibDraw/TextElision.h +++ /dev/null @@ -1,36 +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 - -namespace Gfx { - -enum class TextElision { - None, - Right, -}; - -} diff --git a/Libraries/LibDraw/Triangle.h b/Libraries/LibDraw/Triangle.h deleted file mode 100644 index 23aac1516e..0000000000 --- a/Libraries/LibDraw/Triangle.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2020, Shannon Booth <shannon.ml.booth@gmail.com> - * 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 <LibDraw/Point.h> - -namespace Gfx { - -class Triangle { -public: - Triangle(Point a, Point b, Point c) - : m_a(a) - , m_b(b) - , m_c(c) - { - m_det = (m_b.x() - m_a.x()) * (m_c.y() - m_a.y()) - (m_b.y() - m_a.y()) * (m_c.x() - m_a.x()); - } - - Point a() const { return m_a; } - Point b() const { return m_b; } - Point c() const { return m_c; } - - bool contains(Point p) const - { - int x = p.x(); - int y = p.y(); - - int ax = m_a.x(); - int bx = m_b.x(); - int cx = m_c.x(); - - int ay = m_a.y(); - int by = m_b.y(); - int cy = m_c.y(); - - if (m_det * ((bx - ax) * (y - ay) - (by - ay) * (x - ax)) <= 0) - return false; - if (m_det * ((cx - bx) * (y - by) - (cy - by) * (x - bx)) <= 0) - return false; - if (m_det * ((ax - cx) * (y - cy) - (ay - cy) * (x - cx)) <= 0) - return false; - return true; - } - - String to_string() const { return String::format("(%s,%s,%s)", m_a.to_string().characters(), m_b.to_string().characters(), m_c.to_string().characters()); } - -private: - int m_det; - Point m_a; - Point m_b; - Point m_c; -}; - -inline const LogStream& operator<<(const LogStream& stream, const Triangle& value) -{ - return stream << value.to_string(); -} - -} |