LibGUI: Add support for clip area to texture
This commit is contained in:
parent
ac22e006a4
commit
8a73414e3e
|
@ -32,9 +32,41 @@ namespace LibGUI
|
|||
m_height = new_height;
|
||||
m_pixels = BAN::move(pixels);
|
||||
|
||||
if (m_has_set_clip)
|
||||
set_clip_area(m_clip_x, m_clip_y, m_clip_w, m_clip_h);
|
||||
else
|
||||
{
|
||||
m_clip_w = new_width;
|
||||
m_clip_h = new_height;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void Texture::set_clip_area(int32_t x, int32_t y, uint32_t width, uint32_t height)
|
||||
{
|
||||
m_clip_x = 0;
|
||||
m_clip_y = 0;
|
||||
m_clip_w = this->width();
|
||||
m_clip_h = this->height();
|
||||
|
||||
|
||||
if (!clamp_to_texture(x, y, width, height))
|
||||
{
|
||||
m_clip_h = 0;
|
||||
m_clip_w = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_clip_x = x;
|
||||
m_clip_y = y;
|
||||
m_clip_w = width;
|
||||
m_clip_h = height;
|
||||
}
|
||||
|
||||
m_has_set_clip = true;
|
||||
}
|
||||
|
||||
void Texture::fill_rect(int32_t x, int32_t y, uint32_t width, uint32_t height, uint32_t color)
|
||||
{
|
||||
if (!clamp_to_texture(x, y, width, height))
|
||||
|
@ -44,15 +76,17 @@ namespace LibGUI
|
|||
set_pixel(x + x_off, y + y_off, color);
|
||||
}
|
||||
|
||||
void Texture::copy_texture(const Texture& texture, int32_t x, int32_t y)
|
||||
void Texture::copy_texture(const Texture& texture, int32_t x, int32_t y, uint32_t sub_x, uint32_t sub_y, uint32_t width, uint32_t height)
|
||||
{
|
||||
uint32_t width = texture.width();
|
||||
uint32_t height = texture.height();
|
||||
if (!clamp_to_texture(x, y, width, height))
|
||||
int32_t src_x = sub_x, src_y = sub_y;
|
||||
if (!clamp_to_texture(x, y, src_x, src_y, width, height, texture))
|
||||
return;
|
||||
sub_x = src_x;
|
||||
sub_y = src_y;
|
||||
|
||||
for (uint32_t y_off = 0; y_off < height; y_off++)
|
||||
for (uint32_t x_off = 0; x_off < width; x_off++)
|
||||
set_pixel(x + x_off, y + y_off, texture.get_pixel(x_off, y_off));
|
||||
set_pixel(x + x_off, y + y_off, texture.get_pixel(sub_x + x_off, sub_y + y_off));
|
||||
}
|
||||
|
||||
void Texture::draw_character(uint32_t codepoint, const LibFont::Font& font, int32_t tl_x, int32_t tl_y, uint32_t color)
|
||||
|
@ -132,9 +166,7 @@ namespace LibGUI
|
|||
|
||||
void Texture::copy_rect(int32_t dst_x, int32_t dst_y, int32_t src_x, int32_t src_y, uint32_t width, uint32_t height)
|
||||
{
|
||||
if (!clamp_to_texture(dst_x, dst_y, width, height))
|
||||
return;
|
||||
if (!clamp_to_texture(src_x, src_y, width, height))
|
||||
if (!clamp_to_texture(dst_x, dst_y, src_x, src_y, width, height, *this))
|
||||
return;
|
||||
|
||||
const bool copy_dir = dst_y < src_y;
|
||||
|
@ -151,10 +183,10 @@ namespace LibGUI
|
|||
|
||||
bool Texture::clamp_to_texture(int32_t& signed_x, int32_t& signed_y, uint32_t& width, uint32_t& height) const
|
||||
{
|
||||
const int32_t min_x = BAN::Math::max<int32_t>(signed_x, 0);
|
||||
const int32_t min_y = BAN::Math::max<int32_t>(signed_y, 0);
|
||||
const int32_t max_x = BAN::Math::min<int32_t>(this->width(), signed_x + (int32_t)width);
|
||||
const int32_t max_y = BAN::Math::min<int32_t>(this->height(), signed_y + (int32_t)height);
|
||||
const int32_t min_x = BAN::Math::max<int32_t>(signed_x, m_clip_x);
|
||||
const int32_t min_y = BAN::Math::max<int32_t>(signed_y, m_clip_y);
|
||||
const int32_t max_x = BAN::Math::min<int32_t>(signed_x + (int32_t)width, m_clip_x + m_clip_w);
|
||||
const int32_t max_y = BAN::Math::min<int32_t>(signed_y + (int32_t)height, m_clip_y + m_clip_h);
|
||||
|
||||
if (min_x >= max_x)
|
||||
return false;
|
||||
|
@ -163,9 +195,63 @@ namespace LibGUI
|
|||
|
||||
signed_x = min_x;
|
||||
signed_y = min_y;
|
||||
width = max_x - min_x;
|
||||
width = max_x - min_x;
|
||||
height = max_y - min_y;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Texture::clamp_to_texture(int32_t& dst_x, int32_t& dst_y, int32_t& src_x, int32_t& src_y, uint32_t& width, uint32_t& height, const Texture& texture) const
|
||||
{
|
||||
if (width > texture.width())
|
||||
width = texture.width();
|
||||
if (height > texture.height())
|
||||
height = texture.height();
|
||||
|
||||
if (dst_x >= static_cast<int32_t>(m_clip_x + m_clip_w))
|
||||
return false;
|
||||
if (dst_y >= static_cast<int32_t>(m_clip_y + m_clip_h))
|
||||
return false;
|
||||
|
||||
if (src_x >= static_cast<int32_t>(texture.width()))
|
||||
return false;
|
||||
if (src_y >= static_cast<int32_t>(texture.height()))
|
||||
return false;
|
||||
|
||||
if (dst_x + static_cast<int32_t>(width) > static_cast<int32_t>(m_clip_x + m_clip_w))
|
||||
width = m_clip_x + m_clip_w - dst_x;
|
||||
if (src_x + static_cast<int32_t>(width) > static_cast<int32_t>(texture.width()))
|
||||
width = texture.width() - src_x;
|
||||
|
||||
if (dst_y + static_cast<int32_t>(height) > static_cast<int32_t>(m_clip_y + m_clip_h))
|
||||
height = m_clip_y + m_clip_h - dst_y;
|
||||
if (src_y + static_cast<int32_t>(height) > static_cast<int32_t>(texture.height()))
|
||||
height = texture.height() - src_y;
|
||||
|
||||
int32_t off_x = 0;
|
||||
if (dst_x < static_cast<int32_t>(m_clip_x))
|
||||
off_x = m_clip_x - dst_x;
|
||||
if (src_x + off_x < 0)
|
||||
off_x = -src_x;
|
||||
if (off_x >= static_cast<int32_t>(width))
|
||||
return false;
|
||||
|
||||
int32_t off_y = 0;
|
||||
if (dst_y < static_cast<int32_t>(m_clip_y))
|
||||
off_y = m_clip_y - dst_y;
|
||||
if (src_y + off_y < 0)
|
||||
off_y = -src_y;
|
||||
if (off_y >= static_cast<int32_t>(height))
|
||||
return false;
|
||||
|
||||
dst_x += off_x;
|
||||
src_x += off_x;
|
||||
dst_y += off_y;
|
||||
src_y += off_y;
|
||||
|
||||
width -= off_x;
|
||||
height -= off_y;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace LibGUI
|
|||
{
|
||||
public:
|
||||
static BAN::ErrorOr<Texture> create(uint32_t width, uint32_t height, uint32_t color);
|
||||
Texture() = default;
|
||||
|
||||
BAN::ErrorOr<void> resize(uint32_t width, uint32_t height);
|
||||
|
||||
|
@ -20,6 +21,10 @@ namespace LibGUI
|
|||
{
|
||||
ASSERT(x < m_width);
|
||||
ASSERT(y < m_height);
|
||||
if (x < m_clip_x || x >= m_clip_x + m_clip_w)
|
||||
return;
|
||||
if (y < m_clip_y || y >= m_clip_y + m_clip_h)
|
||||
return;
|
||||
m_pixels[y * m_width + x] = color;
|
||||
}
|
||||
|
||||
|
@ -32,10 +37,12 @@ namespace LibGUI
|
|||
|
||||
BAN::Span<uint32_t> pixels() { return m_pixels.span(); }
|
||||
|
||||
void set_clip_area(int32_t x, int32_t y, uint32_t width, uint32_t height);
|
||||
|
||||
void fill_rect(int32_t x, int32_t y, uint32_t width, uint32_t height, uint32_t color);
|
||||
void fill(uint32_t color) { return fill_rect(0, 0, width(), height(), color); }
|
||||
|
||||
void copy_texture(const Texture& texture, int32_t x, int32_t y);
|
||||
void copy_texture(const Texture& texture, int32_t x, int32_t y, uint32_t sub_x = 0, uint32_t sub_y = 0, uint32_t width = -1, uint32_t height = -1);
|
||||
|
||||
void draw_character(uint32_t codepoint, const LibFont::Font& font, int32_t x, int32_t y, uint32_t color);
|
||||
void draw_text(BAN::StringView text, const LibFont::Font& font, int32_t x, int32_t y, uint32_t color);
|
||||
|
@ -59,15 +66,19 @@ namespace LibGUI
|
|||
void set_bg_color(uint32_t bg_color) { m_bg_color = bg_color; }
|
||||
|
||||
private:
|
||||
Texture() = default;
|
||||
Texture(BAN::Vector<uint32_t>&& pixels, uint32_t width, uint32_t height, uint32_t color)
|
||||
: m_pixels(BAN::move(pixels))
|
||||
, m_width(width)
|
||||
, m_height(height)
|
||||
, m_bg_color(color)
|
||||
, m_clip_x(0)
|
||||
, m_clip_y(0)
|
||||
, m_clip_w(width)
|
||||
, m_clip_h(height)
|
||||
{}
|
||||
|
||||
bool clamp_to_texture(int32_t& x, int32_t& y, uint32_t& width, uint32_t& height) const;
|
||||
bool clamp_to_texture(int32_t& dst_x, int32_t& dst_y, int32_t& src_x, int32_t& src_y, uint32_t& width, uint32_t& height, const Texture&) const;
|
||||
|
||||
private:
|
||||
BAN::Vector<uint32_t> m_pixels;
|
||||
|
@ -75,6 +86,12 @@ namespace LibGUI
|
|||
uint32_t m_height { 0 };
|
||||
uint32_t m_bg_color { 0xFFFFFFFF };
|
||||
|
||||
uint32_t m_clip_x { 0 };
|
||||
uint32_t m_clip_y { 0 };
|
||||
uint32_t m_clip_w { 0 };
|
||||
uint32_t m_clip_h { 0 };
|
||||
bool m_has_set_clip { false };
|
||||
|
||||
friend class Window;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue