diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-02-07 23:13:47 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-02-07 23:17:06 +0100 |
commit | 887b4a7a1a7d27d6c5bf12024e730fa06b2ab03e (patch) | |
tree | 08f30532b6f16c33ef34b325011162e2b0892bba /SharedGraphics | |
parent | 71b9ec1ae00db9206506dca95930db24c989d530 (diff) | |
download | serenity-887b4a7a1a7d27d6c5bf12024e730fa06b2ab03e.zip |
Start working on a simple Launcher app.
Let GButton have an optional icon (GraphicsBitmap) that gets rendered in the
middle of the button if present.
Also add GraphicsBitmap::load_from_file() which allows mmap'ed RGBA32 files.
I wrote a little program to take "raw" files from GIMP and swizzle them into
the correct byte order.
Diffstat (limited to 'SharedGraphics')
-rw-r--r-- | SharedGraphics/Color.h | 17 | ||||
-rw-r--r-- | SharedGraphics/GraphicsBitmap.cpp | 57 | ||||
-rw-r--r-- | SharedGraphics/GraphicsBitmap.h | 6 | ||||
-rw-r--r-- | SharedGraphics/Painter.cpp | 28 | ||||
-rw-r--r-- | SharedGraphics/Painter.h | 1 | ||||
-rw-r--r-- | SharedGraphics/Point.h | 7 | ||||
-rw-r--r-- | SharedGraphics/Size.h | 2 |
7 files changed, 114 insertions, 4 deletions
diff --git a/SharedGraphics/Color.h b/SharedGraphics/Color.h index b38ecbb5ab..934e6bdd13 100644 --- a/SharedGraphics/Color.h +++ b/SharedGraphics/Color.h @@ -29,9 +29,20 @@ public: Color(byte r, byte g, byte b) : m_value((r << 16) | (g << 8) | b) { } Color(RGBA32 rgba) : m_value(rgba) { } - int red() const { return (m_value >> 16) & 0xff; } - int green() const { return (m_value >> 8) & 0xff; } - int blue() const { return m_value & 0xff; } + byte red() const { return (m_value >> 16) & 0xff; } + byte green() const { return (m_value >> 8) & 0xff; } + byte blue() const { return m_value & 0xff; } + byte alpha() const { return (m_value >> 24) & 0xff; } + + Color blend(Color source) const + { + RGBA32 redblue1 = ((0x100u - source.alpha()) * (m_value & 0xff00ff)) >> 8; + RGBA32 redblue2 = (source.alpha() * (source.m_value & 0xff00ff)) >> 8; + RGBA32 green1 = ((0x100u - source.alpha()) * (m_value & 0x00ff00)) >> 8; + RGBA32 green2 = (source.alpha() * (source.m_value & 0x00ff00)) >> 8; + return Color(((redblue1 | redblue2) & 0xff00ff) + ((green1 | green2) & 0x00ff00)); + } + RGBA32 value() const { return m_value; } diff --git a/SharedGraphics/GraphicsBitmap.cpp b/SharedGraphics/GraphicsBitmap.cpp index 8c8b6c0949..d812218cfe 100644 --- a/SharedGraphics/GraphicsBitmap.cpp +++ b/SharedGraphics/GraphicsBitmap.cpp @@ -1,5 +1,4 @@ #include "GraphicsBitmap.h" -#include <AK/kmalloc.h> #ifdef KERNEL #include <Kernel/Process.h> @@ -7,6 +6,14 @@ #include <WindowServer/WSMessageLoop.h> #endif +#ifdef USERLAND +#include <sys/mman.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#endif + #ifdef KERNEL RetainPtr<GraphicsBitmap> GraphicsBitmap::create(Process& process, const Size& size) { @@ -39,6 +46,49 @@ RetainPtr<GraphicsBitmap> GraphicsBitmap::create_wrapper(const Size& size, RGBA3 return adopt(*new GraphicsBitmap(size, data)); } +RetainPtr<GraphicsBitmap> GraphicsBitmap::load_from_file(const String& path, const Size& size) +{ +#ifdef USERLAND + int fd = open(path.characters(), O_RDONLY, 0644); + if (fd < 0) { + dbgprintf("open(%s) got fd=%d, failed: %s\n", path.characters(), fd, strerror(errno)); + perror("open"); + return nullptr; + } + + auto* mapped_file = (RGBA32*)mmap(nullptr, size.area() * 4, PROT_READ, MAP_SHARED, fd, 0); + if (mapped_file == MAP_FAILED) { + int rc = close(fd); + ASSERT(rc == 0); + return nullptr; + } +#else + int error; + auto descriptor = VFS::the().open(path, error, 0, 0, *VFS::the().root_inode()); + if (!descriptor) { + kprintf("Failed to load GraphicsBitmap from file (%s)\n", path.characters()); + ASSERT_NOT_REACHED(); + } + auto* region = current->allocate_file_backed_region(LinearAddress(), size.area() * 4, descriptor->inode(), ".rgb file", /*readable*/true, /*writable*/false); + region->page_in(); + auto* mapped_file = (RGBA32*)region->laddr().get(); +#endif + + +#ifdef USERLAND + int rc = close(fd); + ASSERT(rc == 0); +#endif + auto bitmap = create_wrapper(size, mapped_file); +#ifdef KERNEL + bitmap->m_server_region = region; +#else + bitmap->m_mmaped = true; +#endif + + return bitmap; +} + GraphicsBitmap::GraphicsBitmap(const Size& size, RGBA32* data) : m_size(size) , m_data(data) @@ -53,6 +103,11 @@ GraphicsBitmap::~GraphicsBitmap() m_client_process->deallocate_region(*m_client_region); if (m_server_region) WSMessageLoop::the().server_process().deallocate_region(*m_server_region); +#else + if (m_mmaped) { + int rc = munmap(m_data, m_size.area() * 4); + ASSERT(rc == 0); + } #endif m_data = nullptr; } diff --git a/SharedGraphics/GraphicsBitmap.h b/SharedGraphics/GraphicsBitmap.h index de3f934ad2..861e0d4170 100644 --- a/SharedGraphics/GraphicsBitmap.h +++ b/SharedGraphics/GraphicsBitmap.h @@ -5,6 +5,7 @@ #include "Size.h" #include <AK/Retainable.h> #include <AK/RetainPtr.h> +#include <AK/AKString.h> #ifdef KERNEL #include "Process.h" @@ -16,6 +17,7 @@ public: static RetainPtr<GraphicsBitmap> create(Process&, const Size&); #endif static RetainPtr<GraphicsBitmap> create_wrapper(const Size&, RGBA32*); + static RetainPtr<GraphicsBitmap> load_from_file(const String& path, const Size&); ~GraphicsBitmap(); RGBA32* scanline(int y); @@ -42,6 +44,10 @@ private: RGBA32* m_data { nullptr }; size_t m_pitch { 0 }; +#ifdef USERLAND + bool m_mmaped { false }; +#endif + #ifdef KERNEL WeakPtr<Process> m_client_process; Region* m_client_region { nullptr }; diff --git a/SharedGraphics/Painter.cpp b/SharedGraphics/Painter.cpp index 486352a958..8f7ead9c21 100644 --- a/SharedGraphics/Painter.cpp +++ b/SharedGraphics/Painter.cpp @@ -368,6 +368,7 @@ void Painter::draw_focus_rect(const Rect& rect) void Painter::blit(const Point& position, const GraphicsBitmap& source, const Rect& src_rect) { Rect dst_rect(position, src_rect.size()); + dst_rect.move_by(m_translation); dst_rect.intersect(m_clip_rect); RGBA32* dst = m_target->scanline(dst_rect.y()) + dst_rect.x(); @@ -383,6 +384,33 @@ void Painter::blit(const Point& position, const GraphicsBitmap& source, const Re } } +void Painter::blit_with_alpha(const Point& position, const GraphicsBitmap& source, const Rect& src_rect) +{ + Rect dst_rect(position, src_rect.size()); + dst_rect.move_by(m_translation); + dst_rect.intersect(m_clip_rect); + + RGBA32* dst = m_target->scanline(dst_rect.y()) + dst_rect.x(); + const RGBA32* src = source.scanline(src_rect.top()) + src_rect.left(); + + const unsigned dst_skip = m_target->width(); + const unsigned src_skip = source.width(); + + for (int i = dst_rect.height() - 1; i >= 0; --i) { + for (int x = 0; x < dst_rect.width(); ++x) { + byte alpha = Color(src[x]).alpha(); + if (alpha == 0xff) + dst[x] = src[x]; + else if (!alpha) + continue; + else + dst[x] = Color(dst[x]).blend(src[x]).value(); + } + dst += dst_skip; + src += src_skip; + } +} + void Painter::set_clip_rect(const Rect& rect) { m_clip_rect = Rect::intersection(rect, m_target->rect()); diff --git a/SharedGraphics/Painter.h b/SharedGraphics/Painter.h index dd9b807f2b..eef0675c49 100644 --- a/SharedGraphics/Painter.h +++ b/SharedGraphics/Painter.h @@ -32,6 +32,7 @@ public: void draw_line(const Point&, const Point&, Color); void draw_focus_rect(const Rect&); void blit(const Point&, const GraphicsBitmap&, const Rect& src_rect); + void blit_with_alpha(const Point&, const GraphicsBitmap&, const Rect& src_rect); enum class TextAlignment { TopLeft, CenterLeft, Center, CenterRight }; void draw_text(const Rect&, const String&, TextAlignment = TextAlignment::TopLeft, Color = Color()); diff --git a/SharedGraphics/Point.h b/SharedGraphics/Point.h index 222eddcb46..a0c0e3a4aa 100644 --- a/SharedGraphics/Point.h +++ b/SharedGraphics/Point.h @@ -26,6 +26,13 @@ public: move_by(delta.x(), delta.y()); } + Point translated(int dx, int dy) + { + Point point = *this; + point.move_by(dx, dy); + return point; + } + void constrain(const Rect&); bool operator==(const Point& other) const diff --git a/SharedGraphics/Size.h b/SharedGraphics/Size.h index 4e5a4ea811..87f2c5b088 100644 --- a/SharedGraphics/Size.h +++ b/SharedGraphics/Size.h @@ -13,6 +13,8 @@ public: 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; } |