1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:37:46 +00:00

WindowServer: Load multiple scaled versions of Bitmaps and Cursors

This enables rendering of mixed-scale screen layouts with e.g. high
resolution cursors and window button icons on high-dpi screens while
using lower resolution bitmaps on regular screens.
This commit is contained in:
Tom 2021-06-18 19:21:30 -06:00 committed by Andreas Kling
parent aa15bf81e4
commit 61af9d882e
15 changed files with 269 additions and 99 deletions

View file

@ -6,6 +6,7 @@
#include <AK/LexicalPath.h>
#include <WindowServer/Cursor.h>
#include <WindowServer/Screen.h>
#include <WindowServer/WindowManager.h>
namespace WindowServer {
@ -77,6 +78,7 @@ CursorParams CursorParams::parse_from_filename(const StringView& cursor_path, co
return { default_hotspot };
}
}
return params;
}
@ -93,37 +95,66 @@ CursorParams CursorParams::constrained(const Gfx::Bitmap& bitmap) const
}
}
if (params.m_have_hotspot)
params.m_hotspot = params.m_hotspot.constrained(rect);
params.m_hotspot.constrain(rect);
else
params.m_hotspot = rect.center();
return params;
}
Cursor::Cursor(NonnullRefPtr<Gfx::Bitmap>&& bitmap, const CursorParams& cursor_params)
: m_bitmap(move(bitmap))
, m_params(cursor_params.constrained(*m_bitmap))
, m_rect(m_bitmap->rect())
Cursor::Cursor(NonnullRefPtr<Gfx::Bitmap>&& bitmap, int scale_factor, const CursorParams& cursor_params)
: m_params(cursor_params.constrained(*bitmap))
, m_rect(bitmap->rect())
{
m_bitmaps.set(scale_factor, move(bitmap));
if (m_params.frames() > 1) {
VERIFY(m_rect.width() % m_params.frames() == 0);
m_rect.set_width(m_rect.width() / m_params.frames());
}
}
Cursor::~Cursor()
{
}
NonnullRefPtr<Cursor> Cursor::create(NonnullRefPtr<Gfx::Bitmap>&& bitmap)
NonnullRefPtr<Cursor> Cursor::create(NonnullRefPtr<Gfx::Bitmap>&& bitmap, int scale_factor)
{
auto hotspot = bitmap->rect().center();
return adopt_ref(*new Cursor(move(bitmap), CursorParams(hotspot)));
return adopt_ref(*new Cursor(move(bitmap), scale_factor, CursorParams(hotspot)));
}
NonnullRefPtr<Cursor> Cursor::create(NonnullRefPtr<Gfx::Bitmap>&& bitmap, const StringView& filename)
RefPtr<Cursor> Cursor::create(const StringView& filename, const StringView& default_filename)
{
auto default_hotspot = bitmap->rect().center();
return adopt_ref(*new Cursor(move(bitmap), CursorParams::parse_from_filename(filename, default_hotspot)));
auto cursor = adopt_ref(*new Cursor());
if (cursor->load(filename, default_filename))
return cursor;
return {};
}
bool Cursor::load(const StringView& filename, const StringView& default_filename)
{
bool did_load_any = false;
bool first = true;
auto load_bitmap = [&](const StringView& path, int scale_factor) {
auto bitmap = Gfx::Bitmap::load_from_file(path, scale_factor);
if (bitmap) {
did_load_any = true;
if (first) {
m_params = CursorParams::parse_from_filename(filename, bitmap->rect().center());
m_rect = bitmap->rect();
first = false;
}
m_bitmaps.set(scale_factor, bitmap.release_nonnull());
}
};
Screen::for_each_scale_factor_in_use([&](int scale_factor) {
load_bitmap(filename, scale_factor);
return IterationDecision::Continue;
});
if (!did_load_any) {
Screen::for_each_scale_factor_in_use([&](int scale_factor) {
load_bitmap(default_filename, scale_factor);
return IterationDecision::Continue;
});
}
return did_load_any;
}
RefPtr<Cursor> Cursor::create(Gfx::StandardCursor standard_cursor)