Lephisto/src/gui_image.cpp

104 lines
2.7 KiB
C++

#include "libs.h"
#include "gui_image.h"
#include "l3d.h"
namespace Gui {
Image::~Image(void) {
#pragma message("Warning: Leaking GL textures..")
}
Image::Image(const char* filename) : Widget() {
SDL_Surface* is = IMG_Load(filename);
if(!is) {
fprintf(stderr, "Could not load %s\n", filename);
L3D::Quit();
}
m_imgw = is->w;
m_imgh = is->h;
SetSize(m_imgw, m_imgh);
/* GL textures must be POT, dim > 64. */
int texw, texh;
{
int nbit = 0;
int sz = m_imgw;
while(sz) { sz >>= 1; nbit++; }
texw = MAX(64, 1<<nbit);
sz = m_imgh;
nbit = 0;
while(sz) { sz >>= 1; nbit++; }
texh = MAX(64, 1<<nbit);
}
m_invtexw = 1.0f / texw;
m_invtexh = 1.0f / texh;
SDL_Rect src, dest;
SDL_Surface* s = SDL_CreateRGBSurface(SDL_SWSURFACE, texw, texh, 32,
0xff, 0xff00, 0xff0000, 0xff000000);
/* Just want to directly copy RGBA values, not blend using alpha. */
SDL_SetAlpha(s, 0, 0);
SDL_SetAlpha(is, 0, 0);
SDL_BlitSurface(is, NULL, s, NULL);
/*
* A silly workaround for the GL_LINEAR filtering of the texture, which
* leads to the black bits of the texture leaking in via bilinear filtering.
*/
dest.x = m_imgw; dest.y = 0; dest.w = m_imgw; dest.h = m_imgh;
src.x = m_imgw-1; src.y = 0; src.w=1; src.h = m_imgh;
SDL_BlitSurface(is, &src, s, &dest);
dest.x = 0; dest.y = m_imgh; dest.w = m_imgw; dest.h = m_imgh;
src.x = 0; src.y = m_imgh-1; src.w=m_imgw; src.h = 1;
SDL_BlitSurface(is, &src, s, &dest);
SDL_FreeSurface(is);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &m_tex);
glBindTexture(GL_TEXTURE_2D, m_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texw, texh, 0, GL_RGBA, GL_UNSIGNED_BYTE, s->pixels);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glDisable(GL_TEXTURE_2D);
SDL_FreeSurface(s);
}
void Image::GetSizeRequested(float size[2]) {
size[0] = m_imgw;
size[1] = m_imgh;
}
void Image::Draw(void) {
float allocSize[2];
GetSize(allocSize);
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_tex);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBegin(GL_QUADS);
float w = m_imgw * m_invtexw;
float h = m_imgh * m_invtexh;
glTexCoord2f(0, h);
glVertex2f(0, 0);
glTexCoord2f(w, h);
glVertex2f(allocSize[0],0);
glTexCoord2f(w, 0);
glVertex2f(allocSize[0], allocSize[1]);
glTexCoord2f(0, 0);
glVertex2f(0, allocSize[1]);
glEnd();
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
}
}