mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 15:10:19 +00:00
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.
This commit is contained in:
parent
71b9ec1ae0
commit
887b4a7a1a
Notes:
sideshowbarker
2024-07-19 15:50:11 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/887b4a7a1a7
29 changed files with 293 additions and 11 deletions
BIN
Base/res/icons/FontEditor.png
Normal file
BIN
Base/res/icons/FontEditor.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 500 B |
BIN
Base/res/icons/FontEditor.rgb
Normal file
BIN
Base/res/icons/FontEditor.rgb
Normal file
Binary file not shown.
BIN
Base/res/icons/Terminal.png
Normal file
BIN
Base/res/icons/Terminal.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 980 B |
BIN
Base/res/icons/Terminal.rgb
Normal file
BIN
Base/res/icons/Terminal.rgb
Normal file
Binary file not shown.
BIN
Base/res/icons/file.png
Normal file
BIN
Base/res/icons/file.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 405 B |
BIN
Base/res/icons/file.rgb
Normal file
BIN
Base/res/icons/file.rgb
Normal file
Binary file not shown.
BIN
Base/res/icons/folder.png
Normal file
BIN
Base/res/icons/folder.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
Base/res/icons/folder.rgb
Normal file
BIN
Base/res/icons/folder.rgb
Normal file
Binary file not shown.
BIN
Base/res/icons/generic.png
Normal file
BIN
Base/res/icons/generic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
Base/res/icons/generic.rgb
Normal file
BIN
Base/res/icons/generic.rgb
Normal file
Binary file not shown.
|
@ -26,7 +26,8 @@
|
|||
#include "BochsVGADevice.h"
|
||||
|
||||
//#define SPAWN_GUITEST
|
||||
#define SPAWN_GUITEST2
|
||||
#define SPAWN_LAUNCHER
|
||||
//#define SPAWN_GUITEST2
|
||||
#define SPAWN_CLOCK
|
||||
//#define SPAWN_FONTEDITOR
|
||||
//#define SPAWN_MULTIPLE_SHELLS
|
||||
|
@ -113,6 +114,9 @@ static void init_stage2()
|
|||
#ifdef SPAWN_GUITEST2
|
||||
Process::create_user_process("/bin/guitest2", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, move(environment), tty0);
|
||||
#endif
|
||||
#ifdef SPAWN_LAUNCHER
|
||||
Process::create_user_process("/bin/Launcher", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, move(environment), tty0);
|
||||
#endif
|
||||
#ifdef SPAWN_CLOCK
|
||||
Process::create_user_process("/bin/Clock", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, move(environment), tty0);
|
||||
#endif
|
||||
|
|
|
@ -14,6 +14,8 @@ make -C ../FontEditor clean && \
|
|||
make -C ../FontEditor && \
|
||||
make -C ../Clock clean && \
|
||||
make -C ../Clock && \
|
||||
make -C ../Launcher clean && \
|
||||
make -C ../Launcher && \
|
||||
make clean &&\
|
||||
make && \
|
||||
sudo ./sync.sh
|
||||
|
|
|
@ -10,6 +10,8 @@ make -C ../Terminal clean && \
|
|||
make -C ../Terminal && \
|
||||
make -C ../Clock clean && \
|
||||
make -C ../Clock && \
|
||||
make -C ../Launcher clean && \
|
||||
make -C ../Launcher && \
|
||||
make -C ../Userland clean && \
|
||||
make -C ../Userland && \
|
||||
sudo ./sync.sh
|
||||
|
|
|
@ -47,6 +47,7 @@ cp -v ../Userland/guitest2 mnt/bin/guitest2
|
|||
cp -v ../Userland/sysctl mnt/bin/sysctl
|
||||
cp -v ../Terminal/Terminal mnt/bin/Terminal
|
||||
cp -v ../FontEditor/FontEditor mnt/bin/FontEditor
|
||||
cp -v ../Launcher/Launcher mnt/bin/Launcher
|
||||
cp -v ../Clock/Clock mnt/bin/Clock
|
||||
ln -s FontEditor mnt/bin/ff
|
||||
ln -s Clock mnt/bin/cl
|
||||
|
|
3
Launcher/.gitignore
vendored
Normal file
3
Launcher/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
*.o
|
||||
*.d
|
||||
FontEditor
|
BIN
Launcher/Launcher
Executable file
BIN
Launcher/Launcher
Executable file
Binary file not shown.
34
Launcher/Makefile
Normal file
34
Launcher/Makefile
Normal file
|
@ -0,0 +1,34 @@
|
|||
OBJS = \
|
||||
main.o
|
||||
|
||||
APP = Launcher
|
||||
|
||||
ARCH_FLAGS =
|
||||
STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib -nostdinc
|
||||
USERLAND_FLAGS = -ffreestanding -fno-stack-protector -fno-ident
|
||||
WARNING_FLAGS = -Wextra -Wall -Wundef -Wcast-qual -Wwrite-strings
|
||||
FLAVOR_FLAGS = -march=i386 -mregparm=3 -m32 -fno-exceptions -fno-rtti -fmerge-all-constants -fno-unroll-loops -fno-pie -fno-pic
|
||||
OPTIMIZATION_FLAGS = -Oz -fno-asynchronous-unwind-tables
|
||||
INCLUDE_FLAGS = -I.. -I. -I../LibC
|
||||
|
||||
DEFINES = -DSERENITY -DSANITIZE_PTRS -DUSERLAND
|
||||
|
||||
CXXFLAGS = -MMD -MP $(WARNING_FLAGS) $(OPTIMIZATION_FLAGS) $(USERLAND_FLAGS) $(FLAVOR_FLAGS) $(ARCH_FLAGS) $(STANDARD_FLAGS) $(INCLUDE_FLAGS) $(DEFINES)
|
||||
CXX = clang
|
||||
LD = ld
|
||||
AR = ar
|
||||
LDFLAGS = -static --strip-debug -melf_i386 -e _start --gc-sections
|
||||
|
||||
all: $(APP)
|
||||
|
||||
$(APP): $(OBJS)
|
||||
$(LD) -o $(APP) $(LDFLAGS) $(OBJS) ../LibGUI/LibGUI.a ../LibC/LibC.a
|
||||
|
||||
.cpp.o:
|
||||
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||
|
||||
-include $(OBJS:%.o=%.d)
|
||||
|
||||
clean:
|
||||
@echo "CLEAN"; rm -f $(APPS) $(OBJS) *.d
|
||||
|
79
Launcher/main.cpp
Normal file
79
Launcher/main.cpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
#include <SharedGraphics/GraphicsBitmap.h>
|
||||
#include <LibGUI/GWindow.h>
|
||||
#include <LibGUI/GWidget.h>
|
||||
#include <LibGUI/GButton.h>
|
||||
#include <LibGUI/GEventLoop.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static GWindow* make_launcher_window();
|
||||
|
||||
void handle_sigchld(int)
|
||||
{
|
||||
dbgprintf("Launcher(%d) Got SIGCHLD\n", getpid());
|
||||
int pid = waitpid(-1, nullptr, 0);
|
||||
dbgprintf("Launcher(%d) waitpid() returned %d\n", getpid(), pid);
|
||||
ASSERT(pid > 0);
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
signal(SIGCHLD, handle_sigchld);
|
||||
|
||||
GEventLoop loop;
|
||||
|
||||
auto* launcher_window = make_launcher_window();
|
||||
launcher_window->set_should_exit_app_on_close(true);
|
||||
launcher_window->show();
|
||||
|
||||
return loop.exec();
|
||||
}
|
||||
|
||||
GWindow* make_launcher_window()
|
||||
{
|
||||
auto* window = new GWindow;
|
||||
window->set_title("Launcher");
|
||||
window->set_rect({ 50, 50, 300, 60 });
|
||||
|
||||
auto* widget = new GWidget;
|
||||
window->set_main_widget(widget);
|
||||
widget->set_relative_rect({ 0, 0, 300, 60 });
|
||||
|
||||
auto* terminal_button = new GButton(widget);
|
||||
terminal_button->set_relative_rect({ 5, 5, 50, 50 });
|
||||
terminal_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/Terminal.rgb", { 32, 32 }));
|
||||
|
||||
terminal_button->on_click = [] (GButton&) {
|
||||
pid_t child_pid = fork();
|
||||
if (!child_pid) {
|
||||
execve("/bin/Terminal", nullptr, nullptr);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
};
|
||||
|
||||
auto* font_editor_button = new GButton(widget);
|
||||
font_editor_button->set_relative_rect({ 60, 5, 50, 50 });
|
||||
font_editor_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/FontEditor.rgb", { 32, 32 }));
|
||||
|
||||
font_editor_button->on_click = [] (GButton&) {
|
||||
pid_t child_pid = fork();
|
||||
if (!child_pid) {
|
||||
execve("/bin/FontEditor", nullptr, nullptr);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
};
|
||||
|
||||
auto* guitest_editor_button = new GButton(widget);
|
||||
guitest_editor_button->set_relative_rect({ 115, 5, 50, 50 });
|
||||
guitest_editor_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/generic.rgb", { 32, 32 }));
|
||||
|
||||
guitest_editor_button->on_click = [] (GButton&) {
|
||||
pid_t child_pid = fork();
|
||||
if (!child_pid) {
|
||||
execve("/bin/guitest", nullptr, nullptr);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
};
|
||||
|
||||
return window;
|
||||
}
|
|
@ -55,11 +55,19 @@ void GButton::paint_event(GPaintEvent&)
|
|||
painter.draw_line({ 2, height() - 3 }, { width() - 2, height() - 3 }, shadow_color);
|
||||
}
|
||||
|
||||
if (!caption().is_empty()) {
|
||||
auto text_rect = rect();
|
||||
if (m_being_pressed)
|
||||
text_rect.move_by(1, 1);
|
||||
painter.draw_text(text_rect, caption(), Painter::TextAlignment::Center, Color::Black);
|
||||
if (!caption().is_empty() || m_icon) {
|
||||
auto content_rect = rect();
|
||||
auto icon_location = m_icon ? content_rect.center().translated(-(m_icon->width() / 2), -(m_icon->height() / 2)) : Point();
|
||||
if (m_being_pressed) {
|
||||
content_rect.move_by(1, 1);
|
||||
icon_location.move_by(1, 1);
|
||||
}
|
||||
if (m_icon) {
|
||||
painter.blit_with_alpha(icon_location, *m_icon, m_icon->rect());
|
||||
painter.draw_text(content_rect, caption(), Painter::TextAlignment::Center, Color::Black);
|
||||
} else {
|
||||
painter.draw_text(content_rect, caption(), Painter::TextAlignment::Center, Color::Black);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "GWidget.h"
|
||||
#include <AK/AKString.h>
|
||||
#include <AK/Function.h>
|
||||
#include <SharedGraphics/GraphicsBitmap.h>
|
||||
|
||||
class GButton final : public GWidget {
|
||||
public:
|
||||
|
@ -12,6 +13,10 @@ public:
|
|||
String caption() const { return m_caption; }
|
||||
void set_caption(String&&);
|
||||
|
||||
void set_icon(RetainPtr<GraphicsBitmap>&& icon) { m_icon = move(icon); }
|
||||
const GraphicsBitmap* icon() const { return m_icon.ptr(); }
|
||||
GraphicsBitmap* icon() { return m_icon.ptr(); }
|
||||
|
||||
Function<void(GButton&)> on_click;
|
||||
|
||||
private:
|
||||
|
@ -23,6 +28,7 @@ private:
|
|||
virtual const char* class_name() const override { return "GButton"; }
|
||||
|
||||
String m_caption;
|
||||
RetainPtr<GraphicsBitmap> m_icon;
|
||||
bool m_being_pressed { false };
|
||||
bool m_tracking_cursor { false };
|
||||
};
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ GWindow* make_font_test_window()
|
|||
GWindow* make_launcher_window()
|
||||
{
|
||||
auto* window = new GWindow;
|
||||
window->set_title("Launcher");
|
||||
window->set_title("guitest2");
|
||||
window->set_rect({ 100, 400, 100, 230 });
|
||||
|
||||
auto* widget = new GWidget;
|
||||
|
|
33
Utilities/convert-raw-to-rgb.cpp
Normal file
33
Utilities/convert-raw-to-rgb.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include <stdio.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int main(int argc, char**argv)
|
||||
{
|
||||
int fd = open(argv[1], O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
for (;;) {
|
||||
unsigned buffer;
|
||||
ssize_t nread = read(fd, &buffer, sizeof(buffer));
|
||||
if (nread == 0)
|
||||
break;
|
||||
if (nread < 0) {
|
||||
perror("read");
|
||||
return 1;
|
||||
}
|
||||
unsigned converted = buffer & 0xff00ff00;
|
||||
converted |= (buffer & 0xff0000) >> 16;
|
||||
converted |= (buffer & 0xff) << 16;
|
||||
write(1, &converted, sizeof(unsigned));
|
||||
}
|
||||
int rc = close(fd);
|
||||
if (rc < 0) {
|
||||
perror("close");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue