diff --git a/engine.build.lua b/engine.build.lua index b470ef6..6c263ff 100644 --- a/engine.build.lua +++ b/engine.build.lua @@ -120,6 +120,7 @@ local graphics_module = Module("source/Graphics", { -- Image "Image.cpp", "ImageLoader.cpp", + "Image/IcoFormat.cpp", "OpenGL.cpp", "GL/glad.c", diff --git a/examples/input/InputExample.cpp b/examples/input/InputExample.cpp index 0dc73e0..3fabc98 100644 --- a/examples/input/InputExample.cpp +++ b/examples/input/InputExample.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -11,7 +12,7 @@ void InputExample::init() { m_renderer = new sp::BatchRenderer2D(); - m_tux_texture.create("assets/textures/tux.png"); + m_tux_texture.create("assets/app.ico"); m_kb_sprite.setTexture(m_tux_texture); m_kb_sprite.setColor(sp::Color::Green); @@ -23,6 +24,17 @@ void InputExample::init() m_mouse_sprite.setPosition(sp::vec2f(50, 50)); m_renderer->setCamera(m_camera); + + /* + std::vector modes = sp::DisplayMode::getFullscreenModes(); + for(std::vector::iterator it = modes.begin(); it != modes.end(); it++) { + sp::Log::debug("h:%i, w:%i, d:%i", it->width, it->height, it->bpp); + } + + sp::DisplayMode d = sp::DisplayMode::getDesktopMode(); + + sp::Log::debug("h:%i, w:%i, d:%i", d.width, d.height, d.bpp); + */ } void InputExample::update(double dt) diff --git a/source/Graphics/Image/Decoder.h b/source/Graphics/Image/Decoder.h new file mode 100644 index 0000000..3ffc293 --- /dev/null +++ b/source/Graphics/Image/Decoder.h @@ -0,0 +1,21 @@ + +#ifndef SPECTRE_GRAPHICS_IMAGE_DECODER_H +#define SPECTRE_GRAPHICS_IMAGE_DECODER_H + +namespace sp { + class Image; +} + +namespace sp { +namespace image { + +class Decoder +{ +public : + + virtual bool decode(Image& img, const unsigned char *data, unsigned size) = 0; +}; + +}} // namespace sp::image + +#endif /* SPECTRE_GRAPHICS_IMAGE_DECODER_H */ diff --git a/source/Graphics/Image/IcoFormat.cpp b/source/Graphics/Image/IcoFormat.cpp new file mode 100644 index 0000000..6a5caa4 --- /dev/null +++ b/source/Graphics/Image/IcoFormat.cpp @@ -0,0 +1,89 @@ + +#include "IcoFormat.h" +#include +#include +#include +#include + +namespace sp { +namespace image { + +struct ICONDIRENT { + uint8_t width; // pos 0 + uint8_t height; // pos 1 + uint8_t num_colors; // pos 2 + uint16_t color_planes; // pos 4 + uint16_t bpp; // pos 6 + uint32_t size; // pos 8 + uint32_t offset; // pos 12 +}; + +struct ICONDIR { + uint16_t reseved; + uint16_t type; + uint16_t num_images; +}; + +struct ICONDIRENT* findLargestImage(struct ICONDIRENT *ent, unsigned short size) { + + int cur_index = 0; + unsigned int cur_size = 0; + + for (int i = 0; i < size; i++) { + unsigned int sz = ent[i].width * ent[i].height; + if (sz > cur_size) { + cur_size = sz; + cur_index = i; + } + } + + return ent + cur_index; +} + +bool IcoFormat::decode(Image& img, const unsigned char *data, unsigned size) +{ + struct ICONDIRENT *ent; + struct ICONDIRENT *largest; + unsigned short type; // pos 2 + unsigned short num_images; // pos 4 + + type = data[2] + data[3]; + num_images = data[4] + data[5]; + + // 1 = ICO, 2 = CUR + if (type != 0x0001 || num_images < 1) { + return false; + } + + // Allocate ICONDIRENT for all images in the file. + ent = (struct ICONDIRENT *) malloc(sizeof(struct ICONDIRENT) * num_images); + if (!ent) { + return false; + } + + for (int i = 0; i < num_images; i++) { + unsigned int pos = 6 + (i*16); + ent[i].width = data[pos + 0]; + ent[i].height = data[pos + 1]; + ent[i].num_colors = data[pos + 2]; + ent[i].color_planes = data[pos + 4]; + ent[i].bpp = data[pos + 6]; + ent[i].size = system::ltoh16(data + pos + 8); + ent[i].offset = system::ltoh16(data + pos + 12); + } + + // Find Largest image + largest = findLargestImage(ent, num_images); + + sp::Log::info("%i, %i, %i, %i", largest->num_colors, largest->height, largest->offset, largest->size); + sp::Log::info("%i", largest->bpp); + + + img.loadFromMemory(data + largest->offset, largest->size); + //img.create(PF_RGBA, largest->width, largest->height, data + largest->offset); + + free(ent); + return true; +} + +}} // namespace sp::image diff --git a/source/Graphics/Image/IcoFormat.h b/source/Graphics/Image/IcoFormat.h new file mode 100644 index 0000000..d93018d --- /dev/null +++ b/source/Graphics/Image/IcoFormat.h @@ -0,0 +1,20 @@ + + +#ifndef SPECTRE_GRAPHICS_IMAGE_ICOFORMAT_H +#define SPECTRE_GRAPHICS_IMAGE_ICOFORMAT_H + +#include "Decoder.h" + +namespace sp { +namespace image { + +class IcoFormat : public Decoder +{ +public : + + bool decode(Image& img, const unsigned char *data, unsigned size); +}; + +}} // namespace sp::image + +#endif /* SPECTRE_GRAPHICS_IMAGE_ICOFORMAT_H */ diff --git a/source/Graphics/ImageLoader.cpp b/source/Graphics/ImageLoader.cpp index fc44b3f..2c2d52a 100644 --- a/source/Graphics/ImageLoader.cpp +++ b/source/Graphics/ImageLoader.cpp @@ -5,6 +5,8 @@ #include #include "ImageLoader.h" +#include "Image/IcoFormat.h" + // Disable some file formats that we don't use. #define STBI_NO_PSD #define STBI_NO_PIC @@ -50,6 +52,11 @@ bool ImageLoader::loadFromMemory(const void *data, unsigned size, Image& img) int w, h, n_comp; const stbi_uc *ptr = (const stbi_uc *) data; + if (ptr[0] == 0x0) { + image::IcoFormat ico; + return ico.decode(img, ptr, size); + } + unsigned char *pixels = stbi_load_from_memory(ptr, size, &w, &h, &n_comp, 4); if (pixels) { diff --git a/source/Platform/Unix/X11Display.cpp b/source/Platform/Unix/X11Display.cpp index 968a9c3..fc35cfe 100644 --- a/source/Platform/Unix/X11Display.cpp +++ b/source/Platform/Unix/X11Display.cpp @@ -1,4 +1,5 @@ +#include #include // Prevents conflict with X.h defining "None" #include #include "X11WindowEventHandler.h" @@ -118,7 +119,22 @@ void X11Display::setCaption(const std::string& caption) void X11Display::setIcon(const std::string& icon) { - // TODO: Implement + Image img; + + /* + if (img.loadFromFile(icon)) { + Atom net_wm_icon = getAtom("_NET_WM_ICON", False); + Atom cardinal = getAtom("CARDINAL", False); + unsigned int length = (img.getWidth() + img.getHeight()) * (img.getBpp() / 8); + + XChangeProperty(m_disp, m_win, + net_wm_icon, cardinal, + img.getBpp(), PropModeReplace, + (const unsigned char*) img.getPixels(), + length); + } else { + Log::warn("Failed to set icon %s", icon.c_str()); + } */ } void X11Display::createHiddenCursor()