From dbd64d935e27f7a8bb5a1f146ff0f0d6dfde45f1 Mon Sep 17 00:00:00 2001 From: Rodrigo Braz Monteiro Date: Fri, 13 Apr 2007 03:52:25 +0000 Subject: [PATCH] Almost working gl text code (seemingly uploads and retrieves glyphs fine, but only rendering white rectangles, and there are many things that could be causing that) Originally committed to SVN as r1071. --- aegisub/gl_text.cpp | 163 +++++++++++++++++++++++++++---- aegisub/gl_text.h | 15 ++- aegisub/video_context.cpp | 2 +- aegisub/video_display_visual.cpp | 5 + 4 files changed, 166 insertions(+), 19 deletions(-) diff --git a/aegisub/gl_text.cpp b/aegisub/gl_text.cpp index 57329747c..ec38f22b3 100644 --- a/aegisub/gl_text.cpp +++ b/aegisub/gl_text.cpp @@ -37,6 +37,7 @@ /////////// // Headers #include "gl_text.h" +#include "utils.h" /////////////////// @@ -79,6 +80,17 @@ OpenGLText* OpenGLText::GetInstance() { //////////// // Set font void OpenGLText::DoSetFont(wxString face,int size) { + // No change required + if (size == fontSize && face == fontFace) return; + + // Set font + fontFace = face; + fontSize = size; + font.SetFaceName(fontFace); + font.SetPointSize(size); + + // Delete all old data + Reset(); } @@ -95,6 +107,33 @@ void OpenGLText::DoSetColour(wxColour col,float alpha) { ///////// // Print void OpenGLText::DoPrint(wxString text,int x,int y) { + // Variables + int dx=x,dy=y; + size_t len = text.Length(); + OpenGLTextGlyph glyph; + lineHeight = 16; // FIXME + + // Set OpenGL + // TODO + + // Draw string + for (size_t i=0;i width) return false; + if (y+h > height) return false; // Can fit in this row? if (x + w < width) { @@ -178,21 +233,95 @@ bool OpenGLTextTexture::TryToInsert(OpenGLTextGlyph glyph) { // Can fit the next row? else { - if (w < width) { - y = nextY; - nextY = y+h; - x = 0; - Insert(glyph); - return true; - } + y = nextY; + if (y+h > height) return false; + nextY = y+h; + x = 0; + Insert(glyph); + return true; } - - // Can't fit - return false; } ////////// // Insert void OpenGLTextTexture::Insert(OpenGLTextGlyph glyph) { + // Glyph data + wxString str = wxChar(glyph.value); + int w = glyph.w; + int h = glyph.h; + + // Fill glyph structure + glyph.x1 = float(x)/width; + glyph.y1 = float(y)/height; + glyph.x2 = float(x+w)/width; + glyph.y2 = float(y+h)/height; + glyph.tex = tex; + + // Create bitmap and bind it to a DC + wxBitmap bmp(w,h,24); + wxMemoryDC dc(bmp); + + // Draw text and convert to image + dc.SetFont(OpenGLText::GetFont()); + dc.DrawText(str,0,0); + wxImage img = bmp.ConvertToImage(); + + // Upload image to video memory + const unsigned char* src = img.GetData(); + glTexSubImage2D(GL_TEXTURE_2D,0,x,y,w,h,GL_ALPHA,GL_UNSIGNED_BYTE,src); + if (glGetError()) throw _T("Error uploading glyph data to video memory."); +} + + +//////////////// +// Draw a glyph +void OpenGLTextGlyph::Draw(int x,int y) { + // Store matrix and translate + glPushMatrix(); + glTranslatef((float)x,(float)y,0.0f); + + // Set blend + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + + // Draw quad + glBegin(GL_QUADS); + // Top-left + glTexCoord2f(x1,y1); + glVertex2f(0,0); + // Bottom-left + glTexCoord2f(x1,y2); + glVertex2f(0,h); + // Bottom-right + glTexCoord2f(x2,y2); + glVertex2f(w,h); + // Top-right + glTexCoord2f(x2,y1); + glVertex2f(w,0); + glEnd(); + + // Restore GL state + glDisable(GL_BLEND); + glPopMatrix(); +} + + +///////////////////// +// Get glyph metrics +wxBitmap *OpenGLTextGlyph::tempBmp = NULL; +void OpenGLTextGlyph::GetMetrics() { + // Glyph data + wxCoord desc,lead; + wxString str = wxChar(value); + + // Create bitmap, if needed + if (!tempBmp) tempBmp = new wxBitmap(16,16,24); + + // Get text extents + { + wxMemoryDC dc(*tempBmp); + dc.SetFont(OpenGLText::GetFont()); + dc.GetTextExtent(str,&w,&h,&desc,&lead); + } } diff --git a/aegisub/gl_text.h b/aegisub/gl_text.h index acf9e0a0c..828d08fae 100644 --- a/aegisub/gl_text.h +++ b/aegisub/gl_text.h @@ -46,10 +46,17 @@ ///////////////////// // Glyph information class OpenGLTextGlyph { +private: + static wxBitmap *tempBmp; + public: + int value; int tex; - float x,y; + float x1,y1,x2,y2; int w,h; + + void GetMetrics(); + void Draw(int x,int y); }; typedef std::map glyphMap; @@ -79,6 +86,11 @@ public: class OpenGLText { private: float r,g,b,a; + int lineHeight; + int fontSize; + wxString fontFace; + wxFont font; + static OpenGLText* instance; glyphMap glyphs; @@ -97,6 +109,7 @@ private: void DoPrint(wxString text,int x,int y); public: + static wxFont GetFont() { return GetInstance()->font; } static void SetFont(wxString face,int size) { GetInstance()->DoSetFont(face,size); } static void SetColour(wxColour col,float alpha=1.0f) { GetInstance()->DoSetColour(col,alpha); } static void Print(wxString text,int x,int y) { GetInstance()->DoPrint(text,x,y); } diff --git a/aegisub/video_context.cpp b/aegisub/video_context.cpp index ad9edc8d9..005ff229d 100644 --- a/aegisub/video_context.cpp +++ b/aegisub/video_context.cpp @@ -517,7 +517,7 @@ GLuint VideoContext::GetFrameAsTexture(int n) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); if (glGetError() != 0) throw _T("Error setting wrap_t texture parameter."); - // Load image data into texture + // Allocate texture int height = frame.h; if (frame.format == FORMAT_YV12) height = height * 3 / 2; int tw = SmallestPowerOf2(MAX(frame.pitch[0]/frame.GetBpp(0),frame.pitch[1]+frame.pitch[2])); diff --git a/aegisub/video_display_visual.cpp b/aegisub/video_display_visual.cpp index e7296ee1a..72c34aeb0 100644 --- a/aegisub/video_display_visual.cpp +++ b/aegisub/video_display_visual.cpp @@ -54,6 +54,7 @@ #include "subs_edit_box.h" #include "export_visible_lines.h" #include "utils.h" +#include "gl_text.h" /////////////// @@ -499,6 +500,10 @@ void VideoDisplayVisual::DrawOverlay() { glEnd(); glDisable(GL_COLOR_LOGIC_OP); + // Setup text + OpenGLText::SetFont(_T("Verdana"),10); + OpenGLText::Print(mouseText,x,y); + //// Setup text //wxFont font(10,wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD,false,_T("Verdana")); //dc.SetFont(font);