summaryrefslogtreecommitdiffstats
path: root/Project/wxGLString.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Project/wxGLString.cpp')
-rw-r--r--Project/wxGLString.cpp503
1 files changed, 503 insertions, 0 deletions
diff --git a/Project/wxGLString.cpp b/Project/wxGLString.cpp
new file mode 100644
index 0000000..b54a953
--- /dev/null
+++ b/Project/wxGLString.cpp
@@ -0,0 +1,503 @@
+#include "wxGLString.h"
+
+#ifdef __WXMAC__
+#include "OpenGL/gl.h"
+#else
+#include <GL/gl.h>
+#endif
+
+#include "wx/wx.h"
+
+
+GLuint* loadImage(wxImage* img)
+{
+
+ GLuint* ID=new GLuint[1];
+ glGenTextures( 1, &ID[0] );
+
+ glBindTexture( GL_TEXTURE_2D, *ID );
+
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1 );
+
+ const int w = img->GetWidth(), h = img->GetHeight();
+
+
+ // note: must make a local copy before passing the data to OpenGL, as GetData() returns RGB
+ // and we want the Alpha channel. Furthermore, the current rendering is black-on-white, we'll
+ // convert it to an alpha channel by the way (not all platforms support transparency in wxDCs
+ // so it's the easiest way to go)
+ GLubyte *bitmapData=img->GetData();
+ GLubyte *imageData;
+
+ int bytesPerPixel = 4;
+
+ int imageSize = w * h * bytesPerPixel;
+ imageData=(GLubyte *)malloc(imageSize);
+
+ int rev_val=h-1;
+
+ for(int y=0; y<h; y++)
+ {
+ for(int x=0; x<w; x++)
+ {
+ imageData[(x+y*w)*bytesPerPixel+0] = 255;
+ imageData[(x+y*w)*bytesPerPixel+1] = 255;
+ imageData[(x+y*w)*bytesPerPixel+2] = 255;
+
+ // alpha
+ imageData[(x+y*w)*bytesPerPixel+3] = 255 - bitmapData[( x+(rev_val-y)*w)*3];
+ }//next
+ }//next
+
+ glTexImage2D(GL_TEXTURE_2D, 0, bytesPerPixel, w, h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, imageData);
+
+ free(imageData);
+
+ // set texture parameters as you wish
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ // GL_CLAMP_TO_EDGE
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+
+ return ID;
+
+}
+
+
+class TextTexture
+{
+ friend class wxGLString;
+ friend class wxGLStringArray;
+ friend class wxGLStringNumber;
+private:
+ GLuint* ID;
+protected:
+
+ GLuint* getID();
+
+ TextTexture();
+ TextTexture(wxBitmap& bmp);
+ void load(wxImage* img);
+public:
+
+
+ ~TextTexture();
+
+};
+
+#if 0
+#pragma mark -
+#pragma mark TextGLDrawable implementation
+#endif
+
+
+TextGLDrawable::TextGLDrawable(TextTexture* image_arg)
+{
+ x=0;
+ y=0;
+ angle=0;
+
+ xscale=1;
+ yscale=1;
+
+ xflip=false;
+ yflip=false;
+
+ if(image_arg!=NULL) setImage(image_arg);
+ else image=NULL;
+
+ tex_coord_x1 = 0;
+ tex_coord_y1 = 1;
+ tex_coord_x2 = 1;
+ tex_coord_y2 = 0;
+}
+
+void TextGLDrawable::setFlip(bool x, bool y)
+{
+ xflip=x;
+ yflip=y;
+}
+
+void TextGLDrawable::move(double x, double y)
+{
+ TextGLDrawable::x=x;
+ TextGLDrawable::y=y;
+}
+
+void TextGLDrawable::scale(float x, float y)
+{
+ TextGLDrawable::xscale=x;
+ TextGLDrawable::yscale=y;
+}
+
+void TextGLDrawable::scale(float k)
+{
+ TextGLDrawable::xscale=k;
+ TextGLDrawable::yscale=k;
+}
+
+void TextGLDrawable::setImage(TextTexture* image)
+{
+ TextGLDrawable::image=image;
+}
+
+void TextGLDrawable::rotate(int angle)
+{
+ TextGLDrawable::angle=angle;
+}
+
+void TextGLDrawable::render() const
+{
+ assert(image!=NULL);
+
+ glPushMatrix();
+ glTranslatef(x - w/2, y - h/2, 0);
+ if(xscale!=1 || yscale!=1) glScalef(xscale, yscale, 1);
+ if(angle!=0) glRotatef(angle, 0,0,1);
+
+
+ glBegin(GL_QUADS);
+
+ glTexCoord2f(xflip? tex_coord_x2 : tex_coord_x1,
+ yflip? tex_coord_y2 : tex_coord_y1);
+ glVertex2f( 0, 0 );
+
+ glTexCoord2f(xflip? tex_coord_x1 : tex_coord_x2,
+ yflip? tex_coord_y2 : tex_coord_y1);
+ glVertex2f( w, 0 );
+
+ glTexCoord2f(xflip? tex_coord_x1 : tex_coord_x2,
+ yflip? tex_coord_y1 : tex_coord_y2);
+ glVertex2f( w, h );
+
+ glTexCoord2f(xflip? tex_coord_x2 : tex_coord_x1,
+ yflip? tex_coord_y1 : tex_coord_y2);
+ glVertex2f( 0, h );
+
+ glEnd();
+ glPopMatrix();
+}
+
+
+#if 0
+#pragma mark -
+#pragma mark TextTexture implementation
+#endif
+
+TextTexture::TextTexture()
+{
+}
+
+TextTexture::TextTexture(wxBitmap& bmp)
+{
+ wxImage img = bmp.ConvertToImage();
+ load(&img);
+}
+void TextTexture::load(wxImage* img)
+{
+ ID=loadImage(img);
+}
+
+GLuint* TextTexture::getID()
+{
+ return ID;
+}
+
+TextTexture::~TextTexture()
+{
+ //glDeleteTextures (1, ID);
+ glDeleteTextures (1, ID);
+ delete ID;
+}
+
+
+#if 0
+#pragma mark -
+#pragma mark wxGLString implementation
+#endif
+
+wxGLString::wxGLString() : wxString(wxT("")), TextGLDrawable()
+{
+ img = NULL;
+}
+wxGLString::wxGLString(wxString message) : wxString(message), TextGLDrawable()
+{
+ img = NULL;
+}
+void wxGLString::operator=(wxString& string)
+{
+ (*((wxString*)this))=string;
+}
+void wxGLString::bind() const
+{
+ glBindTexture(GL_TEXTURE_2D, img->getID()[0] );
+}
+void wxGLString::calculateSize(wxDC* dc, const bool ignore_font /* when from array */)
+{
+ if(!ignore_font)
+ {
+ if(font.IsOk()) dc->SetFont(font);
+ else dc->SetFont(wxSystemSettings::GetFont(wxSYS_SYSTEM_FONT));
+ }
+
+ dc->GetTextExtent(*this, &w, &h);
+}
+
+void wxGLString::consolidate(wxDC* dc)
+{
+ calculateSize(dc);
+ const int power_of_2_w = std::max(32, (int)pow( (double)2, (int)ceil((float)log((double)w)/log(2.0)) ));
+ const int power_of_2_h = std::max(32, (int)pow( (double)2, (int)ceil((float)log((double)h)/log(2.0)) ));
+
+ wxBitmap bmp(power_of_2_w, power_of_2_h);
+ assert(bmp.IsOk());
+
+ {
+ wxMemoryDC temp_dc(bmp);
+
+ temp_dc.SetBrush(*wxWHITE_BRUSH);
+ temp_dc.Clear();
+
+ if(font.IsOk()) temp_dc.SetFont(font);
+ else temp_dc.SetFont(wxSystemSettings::GetFont(wxSYS_SYSTEM_FONT));
+
+ temp_dc.DrawText(*this, 0, 0);
+ }
+
+ if(img != NULL) delete img;
+ img = new TextTexture(bmp);
+
+ TextGLDrawable::texw = power_of_2_w;
+ TextGLDrawable::texh = power_of_2_h;
+ TextGLDrawable::tex_coord_x2 = (float)w / (float)power_of_2_w;
+ TextGLDrawable::tex_coord_y2 = 1-(float)h / (float)power_of_2_h;
+ TextGLDrawable::tex_coord_y1 = 1;
+
+ TextGLDrawable::setImage(img);
+}
+
+void wxGLString::consolidateFromArray(wxDC* dc, double x, double y)
+{
+ dc->DrawText(*this, x, y);
+}
+
+void wxGLString::setFont(wxFont font)
+{
+ wxGLString::font = font;
+}
+
+void wxGLString::render(const double x, const double y)
+{
+ TextGLDrawable::move(x, y);
+ TextGLDrawable::render();
+}
+wxGLString::~wxGLString()
+{
+ if(img != NULL) delete img;
+}
+
+
+#if 0
+#pragma mark -
+#pragma mark wxGLNumberRenderer implementation
+#endif
+
+wxGLNumberRenderer::wxGLNumberRenderer() : wxGLString( wxT("0 1 2 3 4 5 6 7 8 9 . - ") )
+{
+ number_location = new int[13];
+}
+wxGLNumberRenderer::~wxGLNumberRenderer()
+{
+ delete[] number_location;
+}
+
+void wxGLNumberRenderer::consolidate(wxDC* dc)
+{
+ wxGLString::consolidate(dc);
+
+ if(font.IsOk()) dc->SetFont(font);
+ else dc->SetFont(wxSystemSettings::GetFont(wxSYS_SYSTEM_FONT));
+
+ number_location[0] = 0;
+ number_location[1] = dc->GetTextExtent(wxT("0 ")).GetWidth();
+ number_location[2] = dc->GetTextExtent(wxT("0 1 ")).GetWidth();
+ number_location[3] = dc->GetTextExtent(wxT("0 1 2 ")).GetWidth();
+ number_location[4] = dc->GetTextExtent(wxT("0 1 2 3 ")).GetWidth();
+ number_location[5] = dc->GetTextExtent(wxT("0 1 2 3 4 ")).GetWidth();
+ number_location[6] = dc->GetTextExtent(wxT("0 1 2 3 4 5 ")).GetWidth();
+ number_location[7] = dc->GetTextExtent(wxT("0 1 2 3 4 5 6 ")).GetWidth();
+ number_location[8] = dc->GetTextExtent(wxT("0 1 2 3 4 5 6 7 ")).GetWidth();
+ number_location[9] = dc->GetTextExtent(wxT("0 1 2 3 4 5 6 7 8 ")).GetWidth();
+ number_location[10] = dc->GetTextExtent(wxT("0 1 2 3 4 5 6 7 8 9 ")).GetWidth();
+ number_location[11] = dc->GetTextExtent(wxT("0 1 2 3 4 5 6 7 8 9 . ")).GetWidth();
+ number_location[12] = dc->GetTextExtent(wxT("0 1 2 3 4 5 6 7 8 9 . - ")).GetWidth();
+
+ space_w = dc->GetTextExtent(wxT(" ")).GetWidth();
+}
+void wxGLNumberRenderer::renderNumber(int i, double x, double y)
+{
+ wxString s;
+ s << i;
+ renderNumber(s, x, y);
+}
+void wxGLNumberRenderer::renderNumber(float f, double x, double y)
+{
+ wxString s;
+ s << f;
+ renderNumber(s, x, y);
+}
+void wxGLNumberRenderer::renderNumber(wxString s, double x, double y)
+{
+ const int full_string_w = TextGLDrawable::texw;
+
+ const int char_amount = s.Length();
+ for(int c=0; c<char_amount; c++)
+ {
+ int charid = -1;
+
+ char schar = s[c];
+ switch(schar)
+ {
+ case '0' : charid = 0; break;
+ case '1' : charid = 1; break;
+ case '2' : charid = 2; break;
+ case '3' : charid = 3; break;
+ case '4' : charid = 4; break;
+ case '5' : charid = 5; break;
+ case '6' : charid = 6; break;
+ case '7' : charid = 7; break;
+ case '8' : charid = 8; break;
+ case '9' : charid = 9; break;
+ case '.' :
+ case ',' : charid = 10; break;
+ case '-' : charid = 11; break;
+ default: printf("Warning: character %c unexpected in number!\n", schar); continue;
+ }
+
+ assert( charid != -1 );
+
+ TextGLDrawable::tex_coord_x1 = (float)number_location[charid] / (float)full_string_w;
+ TextGLDrawable::tex_coord_x2 = (float)(number_location[charid+1]-space_w) / (float)full_string_w;
+
+ const int char_width = number_location[charid+1] - number_location[charid] - space_w;
+ TextGLDrawable::w = char_width;
+
+
+ TextGLDrawable::move(x, y);
+ TextGLDrawable::render();
+
+ x += char_width;
+ } // next
+
+ // TextGLDrawable::w = full_string_w;
+}
+
+#if 0
+#pragma mark -
+#pragma mark wxGLStringArray implementation
+#endif
+
+wxGLStringArray::wxGLStringArray()
+{
+ img = NULL;
+}
+wxGLStringArray::wxGLStringArray(const wxString strings_arg[], int amount)
+{
+ img = NULL;
+
+ for(int n=0; n<amount; n++)
+ strings.push_back( wxGLString(strings_arg[n]) );
+}
+wxGLStringArray::~wxGLStringArray()
+{
+ if(img != NULL) delete img;
+}
+
+wxGLString& wxGLStringArray::get(const int id)
+{
+ return strings[id];
+}
+void wxGLStringArray::bind()
+{
+ glBindTexture(GL_TEXTURE_2D, img->getID()[0] );
+}
+void wxGLStringArray::addString(wxString string)
+{
+ strings.push_back( wxGLString(string) );
+}
+void wxGLStringArray::setFont(wxFont font)
+{
+ wxGLStringArray::font = font;
+}
+
+void wxGLStringArray::consolidate(wxDC* dc)
+{
+ int x=0, y=0;
+
+ if(font.IsOk()) dc->SetFont(font);
+ else dc->SetFont(wxSystemSettings::GetFont(wxSYS_SYSTEM_FONT));
+
+ // find how much space we need
+ int longest_string = 0;
+
+ const int amount = strings.size();
+ for(int n=0; n<amount; n++)
+ {
+ strings[n].calculateSize(dc, true);
+ y += strings[n].h;
+ if(strings[n].w > longest_string) longest_string = strings[n].w;
+ }//next
+
+ const int average_string_height = y / amount;
+
+ // split in multiple columns if necessary
+ int column_amount = 1;
+ while (amount/column_amount > 30 && column_amount<10)
+ column_amount ++;
+
+ const int power_of_2_w = pow( (double)2, (int)ceil((float)log((double)longest_string*(double)column_amount)/log(2.0)) );
+ const int power_of_2_h = pow( (double)2, (int)ceil((float)log((double)y/(double)column_amount)/log(2.0)) );
+
+ //std::cout << "bitmap size : " << power_of_2_w << ", " << power_of_2_h << " // " << column_amount << " columns" << std::endl;
+
+ wxBitmap bmp(power_of_2_w, power_of_2_h);
+ assert(bmp.IsOk());
+
+ {
+ wxMemoryDC temp_dc(bmp);
+
+ temp_dc.SetBrush(*wxWHITE_BRUSH);
+ temp_dc.Clear();
+
+ y = 0;
+ x = 0;
+ if(font.IsOk()) temp_dc.SetFont(font);
+ else temp_dc.SetFont(wxSystemSettings::GetFont(wxSYS_SYSTEM_FONT));
+
+ for(int n=0; n<amount; n++)
+ {
+ strings[n].consolidateFromArray(&temp_dc, x, y);
+
+ strings[n].tex_coord_x1 = (float)x/(float)power_of_2_w;
+ strings[n].tex_coord_y1 = 1.0 - (float)y/(float)power_of_2_h;
+ strings[n].tex_coord_x2 = (float)(x+strings[n].w)/(float)power_of_2_w;
+ strings[n].tex_coord_y2 = 1.0 - (float)(y+strings[n].h)/(float)power_of_2_h;
+
+ y += strings[n].h;
+ if(y > power_of_2_h - average_string_height) // check if we need to switch to next column
+ {
+ y = 0;
+ x += longest_string;
+ }
+ }
+ }
+ if(img != NULL) delete img;
+ img = new TextTexture(bmp);
+
+ for(int n=0; n<amount; n++)
+ strings[n].setImage(img);
+}