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