usbloadergx/source/libwiigui/gui_image.cpp

462 lines
9.5 KiB
C++
Raw Normal View History

/****************************************************************************
* libwiigui
*
* Tantric 2009
*
* gui_image.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
#include "settings/CSettings.h"
/**
* Constructor for the GuiImage class.
*/
GuiImage::GuiImage()
{
image = NULL;
width = 0;
height = 0;
imageangle = 0;
tile = -1;
stripe = 0;
widescreen = 0;
xx1 = 0;
yy1 = 0;
xx2 = 0;
yy2 = 0;
xx3 = 0;
yy3 = 0;
xx4 = 0;
yy4 = 0;
imgType = IMAGE_DATA;
}
2010-09-24 02:48:03 +02:00
GuiImage::GuiImage(GuiImageData * img)
{
2010-09-24 02:48:03 +02:00
if (img)
{
image = img->GetImage();
width = img->GetWidth();
height = img->GetHeight();
}
else
{
image = NULL;
width = 0;
height = 0;
}
imageangle = 0;
tile = -1;
stripe = 0;
widescreen = 0;
parentangle = true;
xx1 = 0;
yy1 = 0;
xx2 = 0;
yy2 = 0;
xx3 = 0;
yy3 = 0;
xx4 = 0;
yy4 = 0;
imgType = IMAGE_DATA;
}
2010-09-24 02:48:03 +02:00
GuiImage::GuiImage(u8 * img, int w, int h)
{
image = img;
width = w;
height = h;
2010-09-24 02:48:03 +02:00
imageangle = 0;
tile = -1;
stripe = 0;
widescreen = 0;
parentangle = true;
xx1 = 0;
yy1 = 0;
xx2 = 0;
yy2 = 0;
xx3 = 0;
yy3 = 0;
xx4 = 0;
yy4 = 0;
imgType = IMAGE_TEXTURE;
}
2010-09-24 02:48:03 +02:00
GuiImage::GuiImage(int w, int h, GXColor c)
{
2010-09-24 02:48:03 +02:00
image = (u8 *) memalign(32, w * h * 4);
width = w;
height = h;
imageangle = 0;
tile = -1;
stripe = 0;
widescreen = 0;
parentangle = true;
xx1 = 0;
yy1 = 0;
xx2 = 0;
yy2 = 0;
xx3 = 0;
yy3 = 0;
xx4 = 0;
yy4 = 0;
imgType = IMAGE_COLOR;
2010-09-24 02:48:03 +02:00
if (!image) return;
int x, y;
2010-09-24 02:48:03 +02:00
for (y = 0; y < h; y++)
{
2010-09-24 02:48:03 +02:00
for (x = 0; x < w; x++)
{
2010-09-24 02:48:03 +02:00
this->SetPixel(x, y, c);
}
}
int len = w * h * 4;
2010-09-24 02:48:03 +02:00
if (len % 32) len += (32 - len % 32);
DCFlushRange(image, len);
}
2010-09-24 02:48:03 +02:00
GuiImage::GuiImage(GuiImage &srcimage) :
GuiElement()
{
width = srcimage.GetWidth();
height = srcimage.GetHeight();
int len = width * height * 4;
2010-09-24 02:48:03 +02:00
if (len % 32) len += (32 - len % 32);
image = (u8 *) memalign(32, len);
memcpy(image, srcimage.GetImage(), len);
DCFlushRange(image, len);
imageangle = srcimage.GetAngle();
tile = -1;
stripe = 0;
widescreen = 0;
parentangle = true;
xx1 = 0;
yy1 = 0;
xx2 = 0;
yy2 = 0;
xx3 = 0;
yy3 = 0;
xx4 = 0;
yy4 = 0;
imgType = IMAGE_COPY;
}
2010-09-24 02:48:03 +02:00
GuiImage::GuiImage(GuiImage *srcimage) :
GuiElement()
{
width = srcimage->GetWidth();
height = srcimage->GetHeight();
int len = width * height * 4;
2010-09-24 02:48:03 +02:00
if (len % 32) len += (32 - len % 32);
image = (u8 *) memalign(32, len);
memcpy(image, srcimage->GetImage(), len);
DCFlushRange(image, len);
imageangle = srcimage->GetAngle();
tile = -1;
stripe = 0;
widescreen = 0;
parentangle = true;
xx1 = 0;
yy1 = 0;
xx2 = 0;
yy2 = 0;
xx3 = 0;
yy3 = 0;
xx4 = 0;
yy4 = 0;
imgType = IMAGE_COPY;
}
2010-09-24 02:48:03 +02:00
GuiImage &GuiImage::operator=(GuiImage & srcimage)
{
2010-09-24 02:48:03 +02:00
if ((imgType == IMAGE_COLOR || imgType == IMAGE_COPY) && image)
{
2010-09-24 02:48:03 +02:00
free(image);
image = NULL;
}
width = srcimage.GetWidth();
height = srcimage.GetHeight();
int len = width * height * 4;
2010-09-24 02:48:03 +02:00
if (len % 32) len += (32 - len % 32);
image = (u8 *) memalign(32, len);
memcpy(image, srcimage.GetImage(), len);
DCFlushRange(image, len);
imageangle = srcimage.GetAngle();
tile = -1;
stripe = 0;
widescreen = 0;
parentangle = true;
xx1 = 0;
yy1 = 0;
xx2 = 0;
yy2 = 0;
xx3 = 0;
yy3 = 0;
xx4 = 0;
yy4 = 0;
imgType = IMAGE_COPY;
return *this;
}
/**
* Destructor for the GuiImage class.
*/
GuiImage::~GuiImage()
{
2010-09-24 02:48:03 +02:00
if ((imgType == IMAGE_COLOR || imgType == IMAGE_COPY) && image)
{
2010-09-24 02:48:03 +02:00
free(image);
image = NULL;
}
}
u8 * GuiImage::GetImage()
{
return image;
}
2010-09-24 02:48:03 +02:00
void GuiImage::SetImage(GuiImageData * img)
{
LOCK( this );
2010-09-24 02:48:03 +02:00
if ((imgType == IMAGE_COLOR || imgType == IMAGE_COPY) && image)
{
2010-09-24 02:48:03 +02:00
free(image);
image = NULL;
}
image = NULL;
width = 0;
height = 0;
imgType = IMAGE_DATA;
if(img)
{
image = img->GetImage();
width = img->GetWidth();
height = img->GetHeight();
}
}
2010-09-24 02:48:03 +02:00
void GuiImage::SetImage(u8 * img, int w, int h)
{
LOCK( this );
2010-09-24 02:48:03 +02:00
if ((imgType == IMAGE_COLOR || imgType == IMAGE_COPY) && image)
{
2010-09-24 02:48:03 +02:00
free(image);
image = NULL;
}
image = img;
width = w;
height = h;
imgType = IMAGE_TEXTURE;
}
2010-09-24 02:48:03 +02:00
void GuiImage::SetAngle(float a)
{
LOCK( this );
imageangle = a;
}
float GuiImage::GetAngle()
{
return imageangle;
}
2010-09-24 02:48:03 +02:00
void GuiImage::SetTile(int t)
{
LOCK( this );
tile = t;
}
2010-09-24 02:48:03 +02:00
void GuiImage::SetWidescreen(bool w)
{
LOCK( this );
widescreen = w;
}
2010-09-24 02:48:03 +02:00
void GuiImage::SetParentAngle(bool a)
{
LOCK( this );
parentangle = a;
}
2010-09-24 02:48:03 +02:00
GXColor GuiImage::GetPixel(int x, int y)
{
2010-09-24 02:48:03 +02:00
if (!image || this->GetWidth() <= 0 || x < 0 || y < 0) return ( GXColor )
{ 0, 0, 0, 0};
2010-09-24 02:48:03 +02:00
u32 offset = (((y >> 2) << 4) * this->GetWidth()) + ((x >> 2) << 6) + (((y % 4 << 2) + x % 4) << 1);
GXColor color;
2010-09-24 02:48:03 +02:00
color.a = *(image + offset);
color.r = *(image + offset + 1);
color.g = *(image + offset + 32);
color.b = *(image + offset + 33);
return color;
}
2010-09-24 02:48:03 +02:00
void GuiImage::SetPixel(int x, int y, GXColor color)
{
LOCK( this );
2010-09-24 02:48:03 +02:00
if (!image || this->GetWidth() <= 0 || x < 0 || y < 0) return;
u32 offset = (((y >> 2) << 4) * this->GetWidth()) + ((x >> 2) << 6) + (((y % 4 << 2) + x % 4) << 1);
*(image + offset) = color.a;
*(image + offset + 1) = color.r;
*(image + offset + 32) = color.g;
*(image + offset + 33) = color.b;
}
2010-09-24 02:48:03 +02:00
void GuiImage::SetGrayscale(void)
{
LOCK( this );
GXColor color;
u32 offset, gray;
2010-09-24 02:48:03 +02:00
for (int x = 0; x < width; x++)
{
2010-09-24 02:48:03 +02:00
for (int y = 0; y < height; y++)
{
2010-09-24 02:48:03 +02:00
offset = (((y >> 2) << 4) * width) + ((x >> 2) << 6) + (((y % 4 << 2) + x % 4) << 1);
color.r = *(image + offset + 1);
color.g = *(image + offset + 32);
color.b = *(image + offset + 33);
2010-09-24 02:48:03 +02:00
gray = (77 * color.r + 150 * color.g + 28 * color.b) / 255;
2010-09-24 02:48:03 +02:00
*(image + offset + 1) = gray;
*(image + offset + 32) = gray;
*(image + offset + 33) = gray;
}
}
int len = width * height * 4;
2010-09-24 02:48:03 +02:00
if (len % 32) len += (32 - len % 32);
DCFlushRange(image, len);
}
2010-09-24 02:48:03 +02:00
void GuiImage::SetStripe(int s)
{
LOCK( this );
stripe = s;
}
2010-09-24 02:48:03 +02:00
void GuiImage::SetSkew(int XX1, int YY1, int XX2, int YY2, int XX3, int YY3, int XX4, int YY4)
{
xx1 = XX1;
yy1 = YY1;
xx2 = XX2;
yy2 = YY2;
xx3 = XX3;
yy3 = YY3;
xx4 = XX4;
yy4 = YY4;
}
2010-09-24 02:48:03 +02:00
void GuiImage::SetSkew(int *skew)
{
xx1 = *skew++;
yy1 = *skew++;
xx2 = *skew++;
yy2 = *skew++;
xx3 = *skew++;
yy3 = *skew++;
xx4 = *skew++;
yy4 = *skew;
}
2010-09-24 02:48:03 +02:00
void GuiImage::ColorStripe(int shift)
{
LOCK( this );
int x, y;
GXColor color;
int alt = 0;
2010-09-24 02:48:03 +02:00
for (y = 0; y < this->GetHeight(); y++)
{
2010-09-24 02:48:03 +02:00
if (y % 3 == 0) alt ^= 1;
2010-09-24 02:48:03 +02:00
for (x = 0; x < this->GetWidth(); x++)
{
2010-09-24 02:48:03 +02:00
color = GetPixel(x, y);
2010-09-24 02:48:03 +02:00
if (alt)
{
2010-09-24 02:48:03 +02:00
if (color.r < 255 - shift)
color.r += shift;
2010-09-24 02:48:03 +02:00
else color.r = 255;
if (color.g < 255 - shift)
color.g += shift;
2010-09-24 02:48:03 +02:00
else color.g = 255;
if (color.b < 255 - shift)
color.b += shift;
2010-09-24 02:48:03 +02:00
else color.b = 255;
color.a = 255;
}
else
{
2010-09-24 02:48:03 +02:00
if (color.r > shift)
color.r -= shift;
2010-09-24 02:48:03 +02:00
else color.r = 0;
if (color.g > shift)
color.g -= shift;
2010-09-24 02:48:03 +02:00
else color.g = 0;
if (color.b > shift)
color.b -= shift;
2010-09-24 02:48:03 +02:00
else color.b = 0;
color.a = 255;
}
2010-09-24 02:48:03 +02:00
SetPixel(x, y, color);
}
}
int len = width * height * 4;
2010-09-24 02:48:03 +02:00
if (len % 32) len += (32 - len % 32);
DCFlushRange(image, len);
}
/**
* Draw the button on screen
*/
void GuiImage::Draw()
{
LOCK( this );
2010-09-24 02:48:03 +02:00
if (!image || !this->IsVisible() || tile == 0) return;
float currScale = this->GetScale();
int currLeft = this->GetLeft();
float currAngleDyn = this->GetAngleDyn();
2010-09-24 02:48:03 +02:00
if (currAngleDyn && parentangle) imageangle = currAngleDyn;
2010-09-24 02:48:03 +02:00
if (tile > 0)
{
2010-09-24 02:48:03 +02:00
for (int i = 0; i < tile; i++)
Menu_DrawImg(currLeft + width * i, this->GetTop(), zoffset, width, height, image, imageangle,
widescreen ? currScale * Settings.WSFactor : currScale, currScale, this->GetAlpha(), xx1, yy1, xx2, yy2, xx3,
2010-09-24 02:48:03 +02:00
yy3, xx4, yy4);
}
else
{
// temporary (maybe), used to correct offset for scaled images
2010-09-24 02:48:03 +02:00
if (scale != 1) currLeft = currLeft - width / 2 + (width * scale) / 2;
Menu_DrawImg(currLeft, this->GetTop(), zoffset, width, height, image, imageangle, widescreen ? currScale * Settings.WSFactor
2010-09-24 02:48:03 +02:00
: currScale, currScale, this->GetAlpha(), xx1, yy1, xx2, yy2, xx3, yy3, xx4, yy4);
}
2010-09-24 02:48:03 +02:00
if (stripe > 0) for (int y = 0; y < this->GetHeight(); y += 6)
Menu_DrawRectangle(currLeft, this->GetTop() + y, this->GetWidth(), 3, ( GXColor )
{ 0, 0, 0, stripe}, 1);
this->UpdateEffects();
}