diff options
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibGfx/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/CursorParams.cpp | 100 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/CursorParams.h | 37 | ||||
-rw-r--r-- | Userland/Services/WindowServer/Cursor.cpp | 92 | ||||
-rw-r--r-- | Userland/Services/WindowServer/Cursor.h | 30 |
5 files changed, 145 insertions, 115 deletions
diff --git a/Userland/Libraries/LibGfx/CMakeLists.txt b/Userland/Libraries/LibGfx/CMakeLists.txt index b16f1caf50..92625cace3 100644 --- a/Userland/Libraries/LibGfx/CMakeLists.txt +++ b/Userland/Libraries/LibGfx/CMakeLists.txt @@ -8,6 +8,7 @@ set(SOURCES ClassicStylePainter.cpp ClassicWindowTheme.cpp Color.cpp + CursorParams.cpp DDSLoader.cpp DisjointRectSet.cpp Emoji.cpp diff --git a/Userland/Libraries/LibGfx/CursorParams.cpp b/Userland/Libraries/LibGfx/CursorParams.cpp new file mode 100644 index 0000000000..31ae7105ae --- /dev/null +++ b/Userland/Libraries/LibGfx/CursorParams.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <AK/Format.h> +#include <AK/LexicalPath.h> +#include <LibGfx/Bitmap.h> +#include <LibGfx/CursorParams.h> + +namespace Gfx { + +CursorParams CursorParams::parse_from_filename(StringView const& cursor_path, Gfx::IntPoint const& default_hotspot) +{ + LexicalPath path(cursor_path); + auto file_title = path.title(); + auto last_dot_in_title = file_title.find_last('.'); + if (!last_dot_in_title.has_value() || last_dot_in_title.value() == 0) { + // No encoded params in filename. Not an error, we'll just use defaults + return { default_hotspot }; + } + auto params_str = file_title.substring_view(last_dot_in_title.value() + 1); + + CursorParams params(default_hotspot); + bool in_display_scale_part = false; + for (size_t i = 0; i + 1 < params_str.length() && !in_display_scale_part;) { + auto property = params_str[i++]; + + auto value = [&]() -> Optional<size_t> { + size_t k = i; + while (k < params_str.length()) { + auto ch = params_str[k]; + if (ch < '0' || ch > '9') + break; + k++; + } + if (k == i) + return {}; + auto parsed_number = params_str.substring_view(i, k - i).to_uint(); + if (!parsed_number.has_value()) + return {}; + i = k; + return parsed_number.value(); + }(); + if (!value.has_value()) { + dbgln("Failed to parse value for property '{}' from parsed cursor path: {}", property, cursor_path); + return { default_hotspot }; + } + switch (property) { + case 'x': + params.m_hotspot.set_x(value.value()); + params.m_have_hotspot = true; + break; + case 'y': + params.m_hotspot.set_y(value.value()); + params.m_have_hotspot = true; + break; + case 'f': + if (value.value() > 1) + params.m_frames = value.value(); + break; + case 't': + if (value.value() >= 100 && value.value() <= 1000) + params.m_frame_ms = value.value(); + else + dbgln("Cursor frame rate outside of valid range (100-1000ms)"); + break; + case '-': + in_display_scale_part = true; + break; + default: + dbgln("Ignore unknown property '{}' with value {} parsed from cursor path: {}", property, value.value(), cursor_path); + return { default_hotspot }; + } + } + + return params; +} + +CursorParams CursorParams::constrained(Gfx::Bitmap const& bitmap) const +{ + CursorParams params(*this); + auto rect = bitmap.rect(); + if (params.m_frames > 1) { + if (rect.width() % params.m_frames == 0) { + rect.set_width(rect.width() / (int)params.m_frames); + } else { + dbgln("Cannot divide cursor dimensions {} into {} frames", rect, params.m_frames); + params.m_frames = 1; + } + } + if (params.m_have_hotspot) + params.m_hotspot.constrain(rect); + else + params.m_hotspot = rect.center(); + return params; +} + +} diff --git a/Userland/Libraries/LibGfx/CursorParams.h b/Userland/Libraries/LibGfx/CursorParams.h new file mode 100644 index 0000000000..d3bbd07945 --- /dev/null +++ b/Userland/Libraries/LibGfx/CursorParams.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/StringView.h> +#include <LibGfx/Point.h> + +namespace Gfx { + +class CursorParams { +public: + static CursorParams parse_from_filename(StringView const&, Gfx::IntPoint const&); + + CursorParams() = default; + + CursorParams(Gfx::IntPoint const& hotspot) + : m_hotspot(hotspot) + { + } + CursorParams constrained(Gfx::Bitmap const&) const; + + Gfx::IntPoint const& hotspot() const { return m_hotspot; } + unsigned frames() const { return m_frames; } + unsigned frame_ms() const { return m_frame_ms; } + +private: + Gfx::IntPoint m_hotspot; + unsigned m_frames { 1 }; + unsigned m_frame_ms { 0 }; + bool m_have_hotspot { false }; +}; + +} diff --git a/Userland/Services/WindowServer/Cursor.cpp b/Userland/Services/WindowServer/Cursor.cpp index 9481dd4b35..4f5eda1b0b 100644 --- a/Userland/Services/WindowServer/Cursor.cpp +++ b/Userland/Services/WindowServer/Cursor.cpp @@ -11,93 +11,7 @@ namespace WindowServer { -CursorParams CursorParams::parse_from_filename(const StringView& cursor_path, const Gfx::IntPoint& default_hotspot) -{ - LexicalPath path(cursor_path); - auto file_title = path.title(); - auto last_dot_in_title = file_title.find_last('.'); - if (!last_dot_in_title.has_value() || last_dot_in_title.value() == 0) { - // No encoded params in filename. Not an error, we'll just use defaults - return { default_hotspot }; - } - auto params_str = file_title.substring_view(last_dot_in_title.value() + 1); - - CursorParams params(default_hotspot); - bool in_display_scale_part = false; - for (size_t i = 0; i + 1 < params_str.length() && !in_display_scale_part;) { - auto property = params_str[i++]; - - auto value = [&]() -> Optional<size_t> { - size_t k = i; - while (k < params_str.length()) { - auto ch = params_str[k]; - if (ch < '0' || ch > '9') - break; - k++; - } - if (k == i) - return {}; - auto parsed_number = params_str.substring_view(i, k - i).to_uint(); - if (!parsed_number.has_value()) - return {}; - i = k; - return parsed_number.value(); - }(); - if (!value.has_value()) { - dbgln("Failed to parse value for property '{}' from parsed cursor path: {}", property, cursor_path); - return { default_hotspot }; - } - switch (property) { - case 'x': - params.m_hotspot.set_x(value.value()); - params.m_have_hotspot = true; - break; - case 'y': - params.m_hotspot.set_y(value.value()); - params.m_have_hotspot = true; - break; - case 'f': - if (value.value() > 1) - params.m_frames = value.value(); - break; - case 't': - if (value.value() >= 100 && value.value() <= 1000) - params.m_frame_ms = value.value(); - else - dbgln("Cursor frame rate outside of valid range (100-1000ms)"); - break; - case '-': - in_display_scale_part = true; - break; - default: - dbgln("Ignore unknown property '{}' with value {} parsed from cursor path: {}", property, value.value(), cursor_path); - return { default_hotspot }; - } - } - - return params; -} - -CursorParams CursorParams::constrained(const Gfx::Bitmap& bitmap) const -{ - CursorParams params(*this); - auto rect = bitmap.rect(); - if (params.m_frames > 1) { - if (rect.width() % params.m_frames == 0) { - rect.set_width(rect.width() / (int)params.m_frames); - } else { - dbgln("Cannot divide cursor dimensions {} into {} frames", rect, params.m_frames); - params.m_frames = 1; - } - } - if (params.m_have_hotspot) - params.m_hotspot.constrain(rect); - else - params.m_hotspot = rect.center(); - return params; -} - -Cursor::Cursor(NonnullRefPtr<Gfx::Bitmap>&& bitmap, int scale_factor, const CursorParams& cursor_params) +Cursor::Cursor(NonnullRefPtr<Gfx::Bitmap>&& bitmap, int scale_factor, Gfx::CursorParams const& cursor_params) : m_params(cursor_params.constrained(*bitmap)) , m_rect(bitmap->rect()) { @@ -116,7 +30,7 @@ void Cursor::update_rect_if_animated() NonnullRefPtr<Cursor> Cursor::create(NonnullRefPtr<Gfx::Bitmap>&& bitmap, int scale_factor) { auto hotspot = bitmap->rect().center(); - return adopt_ref(*new Cursor(move(bitmap), scale_factor, CursorParams(hotspot))); + return adopt_ref(*new Cursor(move(bitmap), scale_factor, Gfx::CursorParams(hotspot))); } RefPtr<Cursor> Cursor::create(const StringView& filename, const StringView& default_filename) @@ -152,7 +66,7 @@ bool Cursor::load(const StringView& filename, const StringView& default_filename if (did_load_any) { auto& bitmap = this->bitmap(1); m_rect = bitmap.rect(); - m_params = CursorParams::parse_from_filename(filename, m_rect.center()).constrained(bitmap); + m_params = Gfx::CursorParams::parse_from_filename(filename, m_rect.center()).constrained(bitmap); update_rect_if_animated(); } return did_load_any; diff --git a/Userland/Services/WindowServer/Cursor.h b/Userland/Services/WindowServer/Cursor.h index e36ebd2945..0dd939ba02 100644 --- a/Userland/Services/WindowServer/Cursor.h +++ b/Userland/Services/WindowServer/Cursor.h @@ -8,33 +8,11 @@ #include <AK/HashMap.h> #include <LibGfx/Bitmap.h> +#include <LibGfx/CursorParams.h> #include <LibGfx/StandardCursor.h> namespace WindowServer { -class CursorParams { - friend class Cursor; - -public: - static CursorParams parse_from_filename(const StringView&, const Gfx::IntPoint&); - CursorParams(const Gfx::IntPoint& hotspot) - : m_hotspot(hotspot) - { - } - CursorParams constrained(const Gfx::Bitmap&) const; - - const Gfx::IntPoint& hotspot() const { return m_hotspot; } - unsigned frames() const { return m_frames; } - unsigned frame_ms() const { return m_frame_ms; } - -private: - CursorParams() = default; - Gfx::IntPoint m_hotspot; - unsigned m_frames { 1 }; - unsigned m_frame_ms { 0 }; - bool m_have_hotspot { false }; -}; - class Cursor : public RefCounted<Cursor> { public: static RefPtr<Cursor> create(const StringView&, const StringView&); @@ -42,7 +20,7 @@ public: static RefPtr<Cursor> create(Gfx::StandardCursor); ~Cursor() = default; - const CursorParams& params() const { return m_params; } + const Gfx::CursorParams& params() const { return m_params; } const Gfx::Bitmap& bitmap(int scale_factor) const { auto it = m_bitmaps.find(scale_factor); @@ -69,13 +47,13 @@ public: private: Cursor() { } - Cursor(NonnullRefPtr<Gfx::Bitmap>&&, int, const CursorParams&); + Cursor(NonnullRefPtr<Gfx::Bitmap>&&, int, const Gfx::CursorParams&); bool load(const StringView&, const StringView&); void update_rect_if_animated(); HashMap<int, NonnullRefPtr<Gfx::Bitmap>> m_bitmaps; - CursorParams m_params; + Gfx::CursorParams m_params; Gfx::IntRect m_rect; }; |