class CGlyphOGL { public: // CSprite m_Sprite; // int m_nAdvance; GLuint m_nTexture; int m_nWidth; int m_nHeight; float m_fX1; float m_fX2; float m_fY1; float m_fY2; }; class CFontOGL: public CFont { public: CFontOGL(CRendererOGL& iRenderer, const std::string& sName, int nSize); virtual ~CFontOGL(); virtual void Draw(int nX, int nY, const std::string& sText); protected: CRendererOGL& m_iRenderer; CGlyphOGL m_vGlyphs[96]; }; int PowerOfTwo(int nX) { int nResult = 2; while (nResult < nX) { nResult *= 2; } return nResult; } /*** OPEN GL FONT CODE ***/ CFontOGL::CFontOGL(CRendererOGL& iRenderer, const std::string& sName, int nSize): m_iRenderer(iRenderer) { TTF_Font* pFont; SDL_Surface* pSurface; SDL_Color color; char szText[2]; unsigned char* bBuffer; int nTexWidth; int nTexHeight; /* Open font */ pFont = TTF_OpenFont(sName.c_str(), nSize); if (!pFont) { throw CSDLTTFError("TTF_OpenFont"); } /* Draw 32-127 */ color.r = 255; szText[1] = 0; for (int i = 0; i < 96; i++) { CGlyphOGL& Glyph = m_vGlyphs[i]; /* Draw text to surface */ szText[0] = i + 32; pSurface = TTF_RenderText_Solid(pFont, szText, color); /* OpenGL texture dimensions must be 2^n */ nTexWidth = PowerOfTwo(pSurface->w); nTexHeight = PowerOfTwo(pSurface->h); /* Fill glyph struct */ Glyph.m_nWidth = pSurface->w; Glyph.m_nHeight = pSurface->h; Glyph.m_fX1 = 0.0f; Glyph.m_fY1 = 0.0f; Glyph.m_fX2 = static_cast (Glyph.m_nWidth) / static_cast (nTexWidth); Glyph.m_fY2 = static_cast (Glyph.m_nHeight) / static_cast (nTexHeight); /* Fill texture buffer */ bBuffer = new unsigned char[nTexWidth * nTexHeight]; for (int nX = 0; nX < pSurface->w; nX++) { for (int nY = 0; nY < pSurface->h; nY++) { /* o.o */ bBuffer[nY * nTexWidth + nX] = pSurface->format->palette->colors[ static_cast (pSurface->pixels)[nY * pSurface->w + nX] ].r; } } /* Generate the OpenGL texture */ glGenTextures(1, &Glyph.m_nTexture); glBindTexture(GL_TEXTURE_2D, Glyph.m_nTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, nTexWidth, nTexHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, bBuffer); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* Free used buffers */ delete[] bBuffer; SDL_FreeSurface(pSurface); } TTF_CloseFont(pFont); } CFontOGL::~CFontOGL() {} void CFontOGL::Draw(int nX, int nY, const std::string& sName) { glPushMatrix(); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTranslated(nX, nY, 0); glColor3f(1.0f, 1.0f, 1.0f); int nSize = sName.size(); for (int i = 0; i < nSize; i++) { if ( (unsigned char) sName[i] >= 32 && (unsigned char) sName[i] <= 127 ) { CGlyphOGL& Glyph = m_vGlyphs[sName[i] - 32]; glBindTexture(GL_TEXTURE_2D, Glyph.m_nTexture); glBegin(GL_QUADS); glTexCoord2f(Glyph.m_fX1, Glyph.m_fY1); glVertex2i(0, 0); glTexCoord2f(Glyph.m_fX2, Glyph.m_fY1); glVertex2i(Glyph.m_nWidth, 0); glTexCoord2f(Glyph.m_fX2, Glyph.m_fY2); glVertex2i(Glyph.m_nWidth, Glyph.m_nHeight); glTexCoord2f(Glyph.m_fX1, Glyph.m_fY2); glVertex2i(0, Glyph.m_nHeight); glEnd(); glTranslated(Glyph.m_nWidth, 0, 0); } } glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); glPopMatrix(); }