forked from mia/Aegisub
Document gl_text, fix some minor memory leaks and fix a rendering error that happened only in debug builds.
Originally committed to SVN as r4401.
This commit is contained in:
parent
fd00cf9a21
commit
7bf9e41526
3 changed files with 356 additions and 230 deletions
|
@ -34,12 +34,10 @@
|
||||||
/// @ingroup video_output
|
/// @ingroup video_output
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
|
#include <wx/bitmap.h>
|
||||||
#include <wx/dcmemory.h>
|
#include <wx/dcmemory.h>
|
||||||
#include <wx/image.h>
|
#include <wx/image.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -48,34 +46,71 @@
|
||||||
#include "gl_text.h"
|
#include "gl_text.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
OpenGLText::OpenGLText() {
|
|
||||||
r = g = b = a = 1.0f;
|
/// @class OpenGLTextGlyph
|
||||||
|
/// @brief Struct storing the information needed to draw a glyph
|
||||||
|
class OpenGLTextGlyph {
|
||||||
|
public:
|
||||||
|
wxString str; /// String containing the glyph(s) this is for
|
||||||
|
int tex; /// OpenGL texture to draw for this glyph
|
||||||
|
float x1; /// Left x coordinate of this glyph in the containing texture
|
||||||
|
float x2; /// Right x coordinate of this glyph in the containing texture
|
||||||
|
float y1; /// Left y coordinate of this glyph in the containing texture
|
||||||
|
float y2; /// Right y coordinate of this glyph in the containing texture
|
||||||
|
int w; /// Width of the glyph in pixels
|
||||||
|
int h; /// Height of the glyph in pixels
|
||||||
|
|
||||||
|
OpenGLTextGlyph(int value);
|
||||||
|
void Draw(int x,int y) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// @class OpenGLTextTexture
|
||||||
|
/// @brief OpenGL texture which stores one or more glyphs as sprites
|
||||||
|
class OpenGLTextTexture {
|
||||||
|
private:
|
||||||
|
int x; /// Next x coordinate at which a glyph can be inserted
|
||||||
|
int y; /// Next y coordinate at which a glyph can be inserted
|
||||||
|
int nextY; /// Y coordinate of the next line; tracked due to that lines
|
||||||
|
/// are only as tall as needed to fit the glyphs in them
|
||||||
|
int width; /// Width of the texture
|
||||||
|
int height; /// Height of the texture
|
||||||
|
GLuint tex; /// The texture
|
||||||
|
|
||||||
|
/// Insert the glyph into this texture at the current coordinates
|
||||||
|
void Insert(OpenGLTextGlyph &glyph);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// @brief Try to insert a glyph into this texture
|
||||||
|
/// @param[in][out] glyph Texture to insert
|
||||||
|
/// @return Was the texture successfully added?
|
||||||
|
bool TryToInsert(OpenGLTextGlyph &glyph);
|
||||||
|
|
||||||
|
OpenGLTextTexture(OpenGLTextGlyph &glyph);
|
||||||
|
~OpenGLTextTexture();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
OpenGLText::OpenGLText()
|
||||||
|
: r(1.f)
|
||||||
|
, g(1.f)
|
||||||
|
, b(1.f)
|
||||||
|
, a(1.f)
|
||||||
|
, lineHeight(0)
|
||||||
|
, fontSize(0)
|
||||||
|
, fontBold(false)
|
||||||
|
, fontItalics(false)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLText::~OpenGLText() {
|
OpenGLText::~OpenGLText() {
|
||||||
Reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Reset
|
|
||||||
void OpenGLText::Reset() {
|
|
||||||
textures.clear();
|
|
||||||
glyphs.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Get instance
|
|
||||||
/// @return
|
|
||||||
OpenGLText& OpenGLText::GetInstance() {
|
OpenGLText& OpenGLText::GetInstance() {
|
||||||
static OpenGLText instance;
|
static OpenGLText instance;
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Set font
|
|
||||||
/// @param face
|
|
||||||
/// @param size
|
|
||||||
/// @param bold
|
|
||||||
/// @param italics
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
void OpenGLText::DoSetFont(wxString face,int size,bool bold,bool italics) {
|
void OpenGLText::DoSetFont(wxString face,int size,bool bold,bool italics) {
|
||||||
// No change required
|
// No change required
|
||||||
if (size == fontSize && face == fontFace && bold == fontBold && italics == fontItalics) return;
|
if (size == fontSize && face == fontFace && bold == fontBold && italics == fontItalics) return;
|
||||||
|
@ -90,26 +125,18 @@ void OpenGLText::DoSetFont(wxString face,int size,bool bold,bool italics) {
|
||||||
font.SetWeight(bold ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL);
|
font.SetWeight(bold ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL);
|
||||||
|
|
||||||
// Delete all old data
|
// Delete all old data
|
||||||
Reset();
|
textures.clear();
|
||||||
|
glyphs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Set colour
|
|
||||||
/// @param col
|
|
||||||
/// @param alpha
|
|
||||||
///
|
|
||||||
void OpenGLText::DoSetColour(wxColour col,float alpha) {
|
void OpenGLText::DoSetColour(wxColour col,float alpha) {
|
||||||
r = col.Red() / 255.0f;
|
r = col.Red() / 255.f;
|
||||||
g = col.Green() / 255.0f;
|
g = col.Green() / 255.f;
|
||||||
b = col.Blue() / 255.0f;
|
b = col.Blue() / 255.f;
|
||||||
a = alpha;
|
a = alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Print
|
|
||||||
/// @param text
|
|
||||||
/// @param x
|
|
||||||
/// @param y
|
|
||||||
void OpenGLText::DoPrint(const wxString &text,int x,int y) {
|
void OpenGLText::DoPrint(const wxString &text,int x,int y) {
|
||||||
// Set OpenGL
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
@ -130,17 +157,12 @@ void OpenGLText::DoPrint(const wxString &text,int x,int y) {
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Draw a string at (x,y)
|
|
||||||
void OpenGLText::DrawString(const wxString &text,int x,int y) {
|
void OpenGLText::DrawString(const wxString &text,int x,int y) {
|
||||||
// Variables
|
|
||||||
size_t len = text.Length();
|
size_t len = text.Length();
|
||||||
OpenGLTextGlyph glyph;
|
|
||||||
lineHeight = 0;
|
lineHeight = 0;
|
||||||
int dx=x,dy=y;
|
int dx=x,dy=y;
|
||||||
|
|
||||||
// Draw string
|
|
||||||
for (size_t i=0;i<len;i++) {
|
for (size_t i=0;i<len;i++) {
|
||||||
// Get current character
|
|
||||||
int curChar = text[i];
|
int curChar = text[i];
|
||||||
|
|
||||||
// Handle carriage returns
|
// Handle carriage returns
|
||||||
|
@ -151,7 +173,7 @@ void OpenGLText::DrawString(const wxString &text,int x,int y) {
|
||||||
|
|
||||||
// Handle normal glyphs
|
// Handle normal glyphs
|
||||||
else {
|
else {
|
||||||
glyph = GetGlyph(curChar);
|
OpenGLTextGlyph const& glyph = GetGlyph(curChar);
|
||||||
glyph.Draw(dx,dy);
|
glyph.Draw(dx,dy);
|
||||||
dx += glyph.w;
|
dx += glyph.w;
|
||||||
if (glyph.h > lineHeight) lineHeight = glyph.h;
|
if (glyph.h > lineHeight) lineHeight = glyph.h;
|
||||||
|
@ -159,13 +181,8 @@ void OpenGLText::DrawString(const wxString &text,int x,int y) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Calculate text extent
|
void OpenGLText::DoGetExtent(wxString const& text, int &w, int &h) {
|
||||||
/// @param text Text to get the extents of
|
|
||||||
/// @param w [out] Width
|
|
||||||
/// @param h [out] Height
|
|
||||||
void OpenGLText::DoGetExtent(const wxString &text,int &w,int &h) {
|
|
||||||
size_t len = text.Length();
|
size_t len = text.Length();
|
||||||
OpenGLTextGlyph glyph;
|
|
||||||
lineHeight = 0;
|
lineHeight = 0;
|
||||||
int dx=0,dy=0;
|
int dx=0,dy=0;
|
||||||
w = 0;
|
w = 0;
|
||||||
|
@ -186,7 +203,7 @@ void OpenGLText::DoGetExtent(const wxString &text,int &w,int &h) {
|
||||||
|
|
||||||
// Handle normal glyphs
|
// Handle normal glyphs
|
||||||
else {
|
else {
|
||||||
glyph = GetGlyph(curChar);
|
OpenGLTextGlyph const& glyph = GetGlyph(curChar);
|
||||||
dx += glyph.w;
|
dx += glyph.w;
|
||||||
if (glyph.h > lineHeight) lineHeight = glyph.h;
|
if (glyph.h > lineHeight) lineHeight = glyph.h;
|
||||||
}
|
}
|
||||||
|
@ -197,26 +214,15 @@ void OpenGLText::DoGetExtent(const wxString &text,int &w,int &h) {
|
||||||
h = dy+lineHeight;
|
h = dy+lineHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Get a glyph
|
OpenGLTextGlyph const& OpenGLText::GetGlyph(int i) {
|
||||||
/// @param i
|
|
||||||
/// @return
|
|
||||||
OpenGLTextGlyph OpenGLText::GetGlyph(int i) {
|
|
||||||
glyphMap::iterator res = glyphs.find(i);
|
glyphMap::iterator res = glyphs.find(i);
|
||||||
|
|
||||||
// Found
|
|
||||||
if (res != glyphs.end()) return res->second;
|
if (res != glyphs.end()) return res->second;
|
||||||
|
|
||||||
// Not found, create it
|
|
||||||
return CreateGlyph(i);
|
return CreateGlyph(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Create a glyph
|
OpenGLTextGlyph const& OpenGLText::CreateGlyph(int n) {
|
||||||
/// @param n
|
OpenGLTextGlyph &glyph = glyphs.insert(std::make_pair(n, OpenGLTextGlyph(n))).first->second;
|
||||||
OpenGLTextGlyph OpenGLText::CreateGlyph(int n) {
|
|
||||||
// Create glyph
|
|
||||||
OpenGLTextGlyph glyph;
|
|
||||||
glyph.value = n;
|
|
||||||
glyph.GetMetrics();
|
|
||||||
|
|
||||||
// Insert into some texture
|
// Insert into some texture
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
|
@ -229,24 +235,21 @@ OpenGLTextGlyph OpenGLText::CreateGlyph(int n) {
|
||||||
|
|
||||||
// No texture could fit it, create a new one
|
// No texture could fit it, create a new one
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
textures.push_back(new OpenGLTextTexture(glyph.w,glyph.h));
|
textures.push_back(boost::shared_ptr<OpenGLTextTexture>(new OpenGLTextTexture(glyph)));
|
||||||
textures.back()->TryToInsert(glyph);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set glyph and return it
|
|
||||||
glyphs[n] = glyph;
|
|
||||||
return glyph;
|
return glyph;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Texture constructor
|
/// @brief Texture constructor
|
||||||
/// @param w
|
/// @param w
|
||||||
/// @param h
|
/// @param h
|
||||||
OpenGLTextTexture::OpenGLTextTexture(int w,int h) {
|
OpenGLTextTexture::OpenGLTextTexture(OpenGLTextGlyph &glyph) {
|
||||||
using std::max;
|
using std::max;
|
||||||
// Properties
|
|
||||||
x = y = nextY = 0;
|
x = y = nextY = 0;
|
||||||
width = max(SmallestPowerOf2(w), 64);
|
width = max(SmallestPowerOf2(glyph.w), 64);
|
||||||
height = max(SmallestPowerOf2(h), 64);
|
height = max(SmallestPowerOf2(glyph.h), 64);
|
||||||
width = height = max(width, height);
|
width = height = max(width, height);
|
||||||
tex = 0;
|
tex = 0;
|
||||||
|
|
||||||
|
@ -263,20 +266,18 @@ OpenGLTextTexture::OpenGLTextTexture(int w,int h) {
|
||||||
// Allocate texture
|
// Allocate texture
|
||||||
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,width,height,0,GL_ALPHA,GL_UNSIGNED_BYTE,NULL);
|
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,width,height,0,GL_ALPHA,GL_UNSIGNED_BYTE,NULL);
|
||||||
if (glGetError()) throw _T("Internal OpenGL text renderer error: Could not allocate Text Texture");
|
if (glGetError()) throw _T("Internal OpenGL text renderer error: Could not allocate Text Texture");
|
||||||
|
|
||||||
|
TryToInsert(glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLTextTexture::~OpenGLTextTexture() {
|
OpenGLTextTexture::~OpenGLTextTexture() {
|
||||||
if (tex) {
|
if (tex) glDeleteTextures(1, &tex);
|
||||||
glDeleteTextures(1,&tex);
|
|
||||||
tex = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Can fit a glyph in it?
|
/// @brief Can fit a glyph in it?
|
||||||
/// @param glyph
|
/// @param glyph
|
||||||
/// @return
|
/// @return
|
||||||
bool OpenGLTextTexture::TryToInsert(OpenGLTextGlyph &glyph) {
|
bool OpenGLTextTexture::TryToInsert(OpenGLTextGlyph &glyph) {
|
||||||
// Get size
|
|
||||||
int w = glyph.w;
|
int w = glyph.w;
|
||||||
int h = glyph.h;
|
int h = glyph.h;
|
||||||
if (w > width) return false;
|
if (w > width) return false;
|
||||||
|
@ -304,8 +305,6 @@ bool OpenGLTextTexture::TryToInsert(OpenGLTextGlyph &glyph) {
|
||||||
/// @brief Insert
|
/// @brief Insert
|
||||||
/// @param glyph
|
/// @param glyph
|
||||||
void OpenGLTextTexture::Insert(OpenGLTextGlyph &glyph) {
|
void OpenGLTextTexture::Insert(OpenGLTextGlyph &glyph) {
|
||||||
// Glyph data
|
|
||||||
wxString str = wxChar(glyph.value);
|
|
||||||
int w = glyph.w;
|
int w = glyph.w;
|
||||||
int h = glyph.h;
|
int h = glyph.h;
|
||||||
|
|
||||||
|
@ -317,7 +316,7 @@ void OpenGLTextTexture::Insert(OpenGLTextGlyph &glyph) {
|
||||||
glyph.tex = tex;
|
glyph.tex = tex;
|
||||||
|
|
||||||
// Create bitmap and bind it to a DC
|
// Create bitmap and bind it to a DC
|
||||||
wxBitmap bmp(((w+1)/2)*2,((h+1)/2)*2,24);
|
wxBitmap bmp(w + (w & 1), h + (h & 1),24);
|
||||||
wxMemoryDC dc(bmp);
|
wxMemoryDC dc(bmp);
|
||||||
|
|
||||||
// Draw text and convert to image
|
// Draw text and convert to image
|
||||||
|
@ -325,7 +324,7 @@ void OpenGLTextTexture::Insert(OpenGLTextGlyph &glyph) {
|
||||||
dc.Clear();
|
dc.Clear();
|
||||||
dc.SetFont(OpenGLText::GetFont());
|
dc.SetFont(OpenGLText::GetFont());
|
||||||
dc.SetTextForeground(wxColour(255,255,255));
|
dc.SetTextForeground(wxColour(255,255,255));
|
||||||
dc.DrawText(str,0,0);
|
dc.DrawText(glyph.str,0,0);
|
||||||
wxImage img = bmp.ConvertToImage();
|
wxImage img = bmp.ConvertToImage();
|
||||||
|
|
||||||
// Convert to alpha
|
// Convert to alpha
|
||||||
|
@ -334,71 +333,46 @@ void OpenGLTextTexture::Insert(OpenGLTextGlyph &glyph) {
|
||||||
size_t len = imgw*imgh;
|
size_t len = imgw*imgh;
|
||||||
const unsigned char *src = img.GetData();
|
const unsigned char *src = img.GetData();
|
||||||
const unsigned char *read = src;
|
const unsigned char *read = src;
|
||||||
unsigned char *alpha = new unsigned char[len*2];
|
std::vector<unsigned char> alpha(len * 2, 255);
|
||||||
unsigned char *write = alpha;
|
unsigned char *write = &alpha[1];
|
||||||
for (size_t i=0;i<len;i++) {
|
for (size_t i=0;i<len;i++) {
|
||||||
*write++ = 255;
|
*write = *read;
|
||||||
*write++ = *read++;
|
write += 2;
|
||||||
read += 2;
|
read += 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upload image to video memory
|
// Upload image to video memory
|
||||||
glBindTexture(GL_TEXTURE_2D, tex);
|
glBindTexture(GL_TEXTURE_2D, tex);
|
||||||
glTexSubImage2D(GL_TEXTURE_2D,0,x,y,imgw,imgh,GL_LUMINANCE_ALPHA,GL_UNSIGNED_BYTE,alpha);
|
glTexSubImage2D(GL_TEXTURE_2D,0,x,y,imgw,imgh,GL_LUMINANCE_ALPHA,GL_UNSIGNED_BYTE,&alpha[0]);
|
||||||
delete[] alpha;
|
|
||||||
if (glGetError()) throw _T("Internal OpenGL text renderer error: Error uploading glyph data to video memory.");
|
if (glGetError()) throw _T("Internal OpenGL text renderer error: Error uploading glyph data to video memory.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Draw a glyph at (x,y)
|
/// Draw a glyph at (x,y)
|
||||||
/// @param x
|
void OpenGLTextGlyph::Draw(int x,int y) const {
|
||||||
/// @param y
|
|
||||||
void OpenGLTextGlyph::Draw(int x,int y) {
|
|
||||||
// Store matrix and translate
|
// Store matrix and translate
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef((float)x,(float)y,0.0f);
|
glTranslatef((float)x,(float)y,0.0f);
|
||||||
|
|
||||||
// Set texture
|
|
||||||
glBindTexture(GL_TEXTURE_2D, tex);
|
glBindTexture(GL_TEXTURE_2D, tex);
|
||||||
|
|
||||||
// Draw quad
|
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
// Top-left
|
glTexCoord2f(x1,y1); glVertex2f(0,0); // Top-left
|
||||||
glTexCoord2f(x1,y1);
|
glTexCoord2f(x1,y2); glVertex2f(0,h); // Bottom-left
|
||||||
glVertex2f(0,0);
|
glTexCoord2f(x2,y2); glVertex2f(w,h); // Bottom-right
|
||||||
// Bottom-left
|
glTexCoord2f(x2,y1); glVertex2f(w,0); // Top-right
|
||||||
glTexCoord2f(x1,y2);
|
|
||||||
glVertex2f(0,h);
|
|
||||||
// Bottom-right
|
|
||||||
glTexCoord2f(x2,y2);
|
|
||||||
glVertex2f(w,h);
|
|
||||||
// Top-right
|
|
||||||
glTexCoord2f(x2,y1);
|
|
||||||
glVertex2f(w,0);
|
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
// Restore matrix
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLTextGlyph::~OpenGLTextGlyph() {
|
|
||||||
if (tempBmp) delete tempBmp;
|
|
||||||
tempBmp = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
wxBitmap *OpenGLTextGlyph::tempBmp = NULL;
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
void OpenGLTextGlyph::GetMetrics() {
|
OpenGLTextGlyph::OpenGLTextGlyph(int value)
|
||||||
// Glyph data
|
: str(wxChar(value))
|
||||||
|
{
|
||||||
wxCoord desc,lead;
|
wxCoord desc,lead;
|
||||||
wxString str = wxChar(value);
|
|
||||||
|
|
||||||
// Create bitmap, if needed
|
wxBitmap tempBmp(32, 32, 24);
|
||||||
if (!tempBmp) tempBmp = new wxBitmap(16,16,24);
|
wxMemoryDC dc(tempBmp);
|
||||||
|
|
||||||
// Get text extents
|
|
||||||
wxMemoryDC dc(*tempBmp);
|
|
||||||
dc.SetFont(OpenGLText::GetFont());
|
dc.SetFont(OpenGLText::GetFont());
|
||||||
dc.GetTextExtent(str,&w,&h,&desc,&lead);
|
dc.GetTextExtent(str,&w,&h,&desc,&lead);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,15 +34,11 @@
|
||||||
/// @ingroup video_output
|
/// @ingroup video_output
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "boost/shared_ptr.hpp"
|
||||||
|
|
||||||
#include <wx/bitmap.h>
|
|
||||||
#include <wx/font.h>
|
#include <wx/font.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -52,87 +48,12 @@
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class OpenGLTextGlyph;
|
||||||
/// DOCME
|
class OpenGLTextTexture;
|
||||||
/// @class OpenGLTextGlyph
|
|
||||||
/// @brief DOCME
|
|
||||||
///
|
|
||||||
/// DOCME
|
|
||||||
class OpenGLTextGlyph {
|
|
||||||
private:
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
static wxBitmap *tempBmp;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
int value;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
int tex;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
float x1,y1,x2,y2;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
int w,h;
|
|
||||||
|
|
||||||
void GetMetrics();
|
|
||||||
void Draw(int x,int y);
|
|
||||||
|
|
||||||
~OpenGLTextGlyph();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
typedef std::map<int,OpenGLTextGlyph> glyphMap;
|
typedef std::map<int,OpenGLTextGlyph> glyphMap;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
/// @class OpenGLTextTexture
|
|
||||||
/// @brief DOCME
|
|
||||||
///
|
|
||||||
/// DOCME
|
|
||||||
class OpenGLTextTexture {
|
|
||||||
private:
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
int x,y,nextY;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
int width,height;
|
|
||||||
|
|
||||||
void Insert(OpenGLTextGlyph &glyph);
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
GLuint tex;
|
|
||||||
|
|
||||||
bool TryToInsert(OpenGLTextGlyph &glyph);
|
|
||||||
|
|
||||||
OpenGLTextTexture(int w,int h);
|
|
||||||
~OpenGLTextTexture();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class OpenGLText
|
/// @class OpenGLText
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
|
@ -173,56 +94,69 @@ private:
|
||||||
glyphMap glyphs;
|
glyphMap glyphs;
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
std::vector <OpenGLTextTexture*> textures;
|
std::vector<boost::shared_ptr<OpenGLTextTexture> > textures;
|
||||||
|
|
||||||
OpenGLText();
|
OpenGLText();
|
||||||
~OpenGLText();
|
~OpenGLText();
|
||||||
OpenGLText(OpenGLText const&);
|
OpenGLText(OpenGLText const&);
|
||||||
OpenGLText& operator=(OpenGLText const&);
|
OpenGLText& operator=(OpenGLText const&);
|
||||||
|
|
||||||
OpenGLTextGlyph GetGlyph(int i);
|
/// @brief Get the glyph for the character chr, creating it if necessary
|
||||||
OpenGLTextGlyph CreateGlyph(int i);
|
/// @param chr Character to get the glyph of
|
||||||
void Reset();
|
/// @return The appropriate OpenGLTextGlyph
|
||||||
|
OpenGLTextGlyph const& GetGlyph(int chr);
|
||||||
|
/// @brief Create a new glyph
|
||||||
|
OpenGLTextGlyph const& CreateGlyph(int chr);
|
||||||
|
|
||||||
|
/// @brief Get the singleton OpenGLText instance
|
||||||
static OpenGLText& GetInstance();
|
static OpenGLText& GetInstance();
|
||||||
|
/// @brief Set the currently active font
|
||||||
|
/// @param face Name of the desired font
|
||||||
|
/// @param size Size in points of the desired font
|
||||||
|
/// @param bold Should the font be bold?
|
||||||
|
/// @param italics Should the font be italic?
|
||||||
void DoSetFont(wxString face,int size,bool bold,bool italics);
|
void DoSetFont(wxString face,int size,bool bold,bool italics);
|
||||||
|
/// @brief Set the text color
|
||||||
|
/// @param col Color
|
||||||
|
/// @param alpha Alpha value from 0.f-1.f
|
||||||
void DoSetColour(wxColour col,float alpha);
|
void DoSetColour(wxColour col,float alpha);
|
||||||
|
/// @brief Print a string onscreen
|
||||||
|
/// @param text String to print
|
||||||
|
/// @param x x coordinate
|
||||||
|
/// @param y y coordinate
|
||||||
void DoPrint(const wxString &text,int x,int y);
|
void DoPrint(const wxString &text,int x,int y);
|
||||||
void DrawString(const wxString &text,int x,int y);
|
void DrawString(const wxString &text,int x,int y);
|
||||||
|
/// @brief Get the extents of a string printed with the current font in pixels
|
||||||
|
/// @param text String to get extends of
|
||||||
|
/// @param[out] w Width
|
||||||
|
/// @param[out] h Height
|
||||||
void DoGetExtent(const wxString &text,int &w,int &h);
|
void DoGetExtent(const wxString &text,int &w,int &h);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/// @brief Get the currently active font
|
||||||
/// @brief DOCME
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
static wxFont GetFont() { return GetInstance().font; }
|
static wxFont GetFont() { return GetInstance().font; }
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Set the currently active font
|
||||||
/// @param face
|
/// @param face Name of the desired font
|
||||||
/// @param size
|
/// @param size Size in points of the desired font
|
||||||
/// @param bold
|
/// @param bold Should the font be bold?
|
||||||
/// @param italics
|
/// @param italics Should the font be italic?
|
||||||
///
|
|
||||||
static void SetFont(wxString face=_T("Verdana"),int size=10,bool bold=true,bool italics=false) { GetInstance().DoSetFont(face,size,bold,italics); }
|
static void SetFont(wxString face=_T("Verdana"),int size=10,bool bold=true,bool italics=false) { GetInstance().DoSetFont(face,size,bold,italics); }
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Set the text color
|
||||||
/// @param col
|
/// @param col Color
|
||||||
/// @param alpha
|
/// @param alpha Alpha value from 0.f-1.f
|
||||||
///
|
|
||||||
static void SetColour(wxColour col,float alpha=1.0f) { GetInstance().DoSetColour(col,alpha); }
|
static void SetColour(wxColour col,float alpha=1.0f) { GetInstance().DoSetColour(col,alpha); }
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Print a string onscreen
|
||||||
/// @param text
|
/// @param text String to print
|
||||||
/// @param x
|
/// @param x x coordinate
|
||||||
/// @param y
|
/// @param y y coordinate
|
||||||
///
|
|
||||||
static void Print(const wxString &text,int x,int y) { GetInstance().DoPrint(text,x,y); }
|
static void Print(const wxString &text,int x,int y) { GetInstance().DoPrint(text,x,y); }
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Get the extents of a string printed with the current font in pixels
|
||||||
/// @param text
|
/// @param text String to get extends of
|
||||||
/// @param w
|
/// @param[out] w Width
|
||||||
/// @param h
|
/// @param[out] h Height
|
||||||
///
|
|
||||||
static void GetExtent(const wxString &text,int &w,int &h) { GetInstance().DoGetExtent(text,w,h); }
|
static void GetExtent(const wxString &text,int &w,int &h) { GetInstance().DoGetExtent(text,w,h); }
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
<<<<<<< HEAD
|
||||||
// Copyright (c) 2005-2010, Rodrigo Braz Monteiro
|
// Copyright (c) 2005-2010, Rodrigo Braz Monteiro
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
|
@ -212,3 +213,220 @@ public:
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
||||||
|
=======
|
||||||
|
// Copyright (c) 2005-2010, Rodrigo Braz Monteiro
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
// * Neither the name of the Aegisub Group nor the names of its contributors
|
||||||
|
// may be used to endorse or promote products derived from this software
|
||||||
|
// without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Aegisub Project http://www.aegisub.org/
|
||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
|
||||||
|
/// @file video_display.h
|
||||||
|
/// @see video_display.cpp
|
||||||
|
/// @ingroup video main_ui
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef AGI_PRE
|
||||||
|
#include <wx/glcanvas.h>
|
||||||
|
#include <wx/combobox.h>
|
||||||
|
#include <wx/textctrl.h>
|
||||||
|
#include <memory>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Prototypes
|
||||||
|
class VideoSlider;
|
||||||
|
class VideoBox;
|
||||||
|
class VideoOutGL;
|
||||||
|
class IVisualTool;
|
||||||
|
|
||||||
|
struct VideoState {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int w;
|
||||||
|
int h;
|
||||||
|
VideoState() : x(-1), y(-1), w(-1), h(-1) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @class VideoDisplay
|
||||||
|
/// @brief DOCME
|
||||||
|
class VideoDisplay: public wxGLCanvas {
|
||||||
|
/// The unscaled size of the displayed video
|
||||||
|
wxSize origSize;
|
||||||
|
|
||||||
|
/// The frame number currently being displayed
|
||||||
|
int currentFrame;
|
||||||
|
|
||||||
|
/// The width of the canvas in screen pixels
|
||||||
|
int w;
|
||||||
|
/// The height of the canvas in screen pixels
|
||||||
|
int h;
|
||||||
|
|
||||||
|
/// Screen pixels between the left of the canvas and the left of the video
|
||||||
|
int viewport_x;
|
||||||
|
/// The width of the video in screen pixels
|
||||||
|
int viewport_width;
|
||||||
|
/// Screen pixels between the bottom of the canvas and the bottom of the video; used for glViewport
|
||||||
|
int viewport_bottom;
|
||||||
|
/// Screen pixels between the bottom of the canvas and the top of the video; used for coordinate space conversion
|
||||||
|
int viewport_top;
|
||||||
|
/// The height of the video in screen pixels
|
||||||
|
int viewport_height;
|
||||||
|
|
||||||
|
/// Lock to disable mouse updates during resize operations
|
||||||
|
bool locked;
|
||||||
|
|
||||||
|
/// @brief Draw an overscan mask
|
||||||
|
/// @param sizeH The amount of horizontal overscan on one side
|
||||||
|
/// @param sizeV The amount of vertical overscan on one side
|
||||||
|
/// @param colour The color of the mask
|
||||||
|
/// @param alpha The alpha of the mask
|
||||||
|
void DrawOverscanMask(int sizeH, int sizeV, wxColor color, double alpha) const;
|
||||||
|
|
||||||
|
/// @brief Paint event
|
||||||
|
void OnPaint(wxPaintEvent& event);
|
||||||
|
/// @brief Key event handler
|
||||||
|
/// @param event
|
||||||
|
void OnKey(wxKeyEvent &event);
|
||||||
|
/// @brief Mouse event handler
|
||||||
|
/// @param event
|
||||||
|
void OnMouseEvent(wxMouseEvent& event);
|
||||||
|
|
||||||
|
/// @brief NOP event handler
|
||||||
|
void OnEraseBackground(wxEraseEvent &) {}
|
||||||
|
/// @brief Recalculate video positioning and scaling when the available area or zoom changes
|
||||||
|
/// @param event
|
||||||
|
void OnSizeEvent(wxSizeEvent &event);
|
||||||
|
|
||||||
|
/// @brief Copy coordinates of the mouse to the clipboard
|
||||||
|
void OnCopyCoords(wxCommandEvent &);
|
||||||
|
/// @brief Copy the currently display frame to the clipboard, with subtitles
|
||||||
|
void OnCopyToClipboard(wxCommandEvent &);
|
||||||
|
/// @brief Save the currently display frame to a file, with subtitles
|
||||||
|
void OnSaveSnapshot(wxCommandEvent &);
|
||||||
|
/// @brief Copy the currently display frame to the clipboard, without subtitles
|
||||||
|
void OnCopyToClipboardRaw(wxCommandEvent &);
|
||||||
|
/// @brief Save the currently display frame to a file, without subtitles
|
||||||
|
void OnSaveSnapshotRaw(wxCommandEvent &);
|
||||||
|
|
||||||
|
/// The current zoom level, where 1.0 = 100%
|
||||||
|
double zoomValue;
|
||||||
|
|
||||||
|
/// The video position slider
|
||||||
|
VideoSlider *ControlSlider;
|
||||||
|
|
||||||
|
/// The display for the the video position relative to the current subtitle line
|
||||||
|
wxTextCtrl *SubsPosition;
|
||||||
|
|
||||||
|
/// The display for the absolute time of the video position
|
||||||
|
wxTextCtrl *PositionDisplay;
|
||||||
|
|
||||||
|
/// The video renderer
|
||||||
|
std::auto_ptr<VideoOutGL> videoOut;
|
||||||
|
|
||||||
|
/// The active visual typesetting tool
|
||||||
|
std::auto_ptr<IVisualTool> tool;
|
||||||
|
/// The current tool's ID
|
||||||
|
int activeMode;
|
||||||
|
/// The toolbar used by individual typesetting tools
|
||||||
|
wxToolBar* toolBar;
|
||||||
|
|
||||||
|
|
||||||
|
void OnMode(const wxCommandEvent &event);
|
||||||
|
void SetMode(int mode);
|
||||||
|
/// @brief Switch the active tool to a new object of the specified class
|
||||||
|
/// @param T The class of the new visual typsetting tool
|
||||||
|
template <class T> void SetTool();
|
||||||
|
|
||||||
|
/// The current script width
|
||||||
|
int scriptW;
|
||||||
|
/// The current script height
|
||||||
|
int scriptH;
|
||||||
|
|
||||||
|
VideoState video;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// The VideoBox this display is contained in
|
||||||
|
VideoBox *box;
|
||||||
|
|
||||||
|
/// The dropdown box for selecting zoom levels
|
||||||
|
wxComboBox *zoomBox;
|
||||||
|
|
||||||
|
/// Whether the display can be freely resized by the user
|
||||||
|
bool freeSize;
|
||||||
|
|
||||||
|
/// @brief Constructor
|
||||||
|
/// @param parent Pointer to a parent window.
|
||||||
|
/// @param id Window identifier. If -1, will automatically create an identifier.
|
||||||
|
/// @param pos Window position. wxDefaultPosition is (-1, -1) which indicates that wxWidgets should generate a default position for the window.
|
||||||
|
/// @param size Window size. wxDefaultSize is (-1, -1) which indicates that wxWidgets should generate a default size for the window. If no suitable size can be found, the window will be sized to 20x20 pixels so that the window is visible but obviously not correctly sized.
|
||||||
|
/// @param style Window style.
|
||||||
|
/// @param name Window name.
|
||||||
|
VideoDisplay(VideoBox *box, VideoSlider *ControlSlider, wxTextCtrl *PositionDisplay, wxTextCtrl *SubsPosition, wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxPanelNameStr);
|
||||||
|
~VideoDisplay();
|
||||||
|
/// @brief Reset the size of the display to the video size
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
/// @brief Set this video display to the given frame
|
||||||
|
/// @frameNumber The desired frame number
|
||||||
|
void SetFrame(int frameNumber);
|
||||||
|
/// @brief Get the number of the currently displayed framed
|
||||||
|
int GetFrame() const { return currentFrame; }
|
||||||
|
/// @brief Set the range of valid frame numbers for the slider
|
||||||
|
/// @from Minimum frame number
|
||||||
|
/// @to Maximum frame number; must be >= from or strange things may happen
|
||||||
|
void SetFrameRange(int from, int to);
|
||||||
|
|
||||||
|
/// @brief Render the currently visible frame
|
||||||
|
void Render();
|
||||||
|
|
||||||
|
/// @brief Set the cursor to either default or blank
|
||||||
|
/// @param show Whether or not the cursor should be visible
|
||||||
|
void ShowCursor(bool show);
|
||||||
|
/// @brief Set the size of the display based on the current zoom and video resolution
|
||||||
|
void UpdateSize();
|
||||||
|
/// @brief Set the zoom level
|
||||||
|
/// @param value The new zoom level
|
||||||
|
void SetZoom(double value);
|
||||||
|
/// @brief Set the zoom level to that indicated by the dropdown
|
||||||
|
void SetZoomFromBox();
|
||||||
|
/// @brief Get the current zoom level
|
||||||
|
double GetZoom() const;
|
||||||
|
|
||||||
|
/// @brief Convert a point from screen to script coordinate frame
|
||||||
|
/// @param x x coordinate; in/out
|
||||||
|
/// @param y y coordinate; in/out
|
||||||
|
void ToScriptCoords(int *x, int *y) const;
|
||||||
|
/// @brief Convert a point from script to screen coordinate frame
|
||||||
|
/// @param x x coordinate; in/out
|
||||||
|
/// @param y y coordinate; in/out
|
||||||
|
void FromScriptCoords(int *x, int *y) const;
|
||||||
|
|
||||||
|
|
||||||
|
DECLARE_EVENT_TABLE()
|
||||||
|
};
|
||||||
|
>>>>>>> c862d3e... Document gl_text, fix some minor memory leaks and fix a rendering error that happened only in debug builds.
|
||||||
|
|
Loading…
Reference in a new issue