diff --git a/src/framework/color.h b/src/framework/color.h index 1943bc90..77cf2996 100644 --- a/src/framework/color.h +++ b/src/framework/color.h @@ -32,11 +32,6 @@ typedef uint32 RGBA; class Color { public: - enum { - white = 0xFFFFFFFF, - pink = 0xFF00FFFF - }; - inline Color() : color(0) { } inline Color(uint8 r, uint8 g, uint8 b, uint8 a = 0xFF) : color(((r & 0xff)<<24) | ((g & 0xff)<<16) | ((b & 0xff)<<8) | (a & 0xff)) { } inline Color(const Color& other) : color(other.color) { } diff --git a/src/framework/font.cpp b/src/framework/font.cpp index bca01af5..e68fb8c4 100644 --- a/src/framework/font.cpp +++ b/src/framework/font.cpp @@ -27,18 +27,11 @@ #include "textures.h" #include "graphics.h" -#include -#include -#include - Font::Font() : m_lineHeight(14), m_cursorSize(14), - m_color(Color::white), - m_firstGlyph(32), - m_numHorizontalGlyphs(16) + m_color(0xFFFFFFFF) { - bzero(m_glyphWidths, sizeof(m_glyphWidths)); } bool Font::load(const std::string& file) @@ -57,6 +50,10 @@ bool Font::load(const std::string& file) std::istringstream fin(fileContents); std::string textureName; + int numHorizontalGlyphs; + int firstGlyph; + Size glyphSize; + Size textureSize; try { YAML::Parser parser(fin); @@ -67,43 +64,48 @@ bool Font::load(const std::string& file) doc["line height"] >> m_lineHeight; doc["cursor size"] >> m_cursorSize; doc["color"] >> m_color; - doc["first glyph"] >> m_firstGlyph; + doc["first glyph"] >> firstGlyph; + doc["image glyph size"] >> glyphSize; doc["image"] >> textureName; - doc["image glyph size"] >> m_glyphSize; + + m_texture = g_textures.get("fonts/" + textureName); + if(!m_texture) { + error("Failed to load image for font \"%s\"", file.c_str()); + return false; + } + + textureSize = m_texture->getSize(); + numHorizontalGlyphs = textureSize.width() / glyphSize.width(); const YAML::Node& widthsNode = doc["glyph widths"]; for(auto it = widthsNode.begin(); it != widthsNode.end(); ++it) { - int id, width; - it.first() >> id; - it.second() >> width; - m_glyphWidths[id] = width; + int glyph, glyphWidth; + it.first() >> glyph; + it.second() >> glyphWidth; + + // calculate glyph texture coords + m_glyphsTextureCoords[glyph].setRect(((glyph - firstGlyph) % numHorizontalGlyphs) * glyphSize.width(), + ((glyph - firstGlyph) / numHorizontalGlyphs) * glyphSize.height(), + glyphWidth, + glyphSize.height()); + + // store glyph size + m_glyphsSize[glyph].setHeight(glyphSize.height()); + m_glyphsSize[glyph].setWidth(glyphWidth); } } catch (YAML::ParserException& e) { error("Malformed font file \"%s\"", file.c_str()); return false; } - m_texture = g_textures.get("fonts/" + textureName); - m_numHorizontalGlyphs = m_texture->getSize().width() / m_glyphSize.width(); - - if(!m_texture) { - error("Failed to load image for font \"%s\"", file.c_str()); - return false; - } - return true; } void Font::renderText(const Point& pos, const std::string& text) { - // bind font texture - glBindTexture(GL_TEXTURE_2D, m_texture->getTextureId()); - - // set font color - glColor4ubv(m_color.rgbaPtr()); - - // begin render - glBegin(GL_QUADS); + // begin texture rendering + g_graphics.setColor(m_color); + g_graphics._beginTextureRender(m_texture.get()); Point currentPos = pos; const Size& screenSize = g_graphics.getScreenSize(); @@ -112,9 +114,7 @@ void Font::renderText(const Point& pos, const std::string& text) for(int i = 0; i < textLenght; ++i) { int c = (int)text[i]; - // check if is visible - if(currentPos.x >= screenSize.width()) - continue; + // break rendering if the Y pos is below the screen if(currentPos.y >= screenSize.height()) break; @@ -123,45 +123,28 @@ void Font::renderText(const Point& pos, const std::string& text) currentPos.y += m_lineHeight; currentPos.x = pos.x; } - // text eof - else if(c == '\0') { - break; - } - // normal glyph - else if(c >= m_firstGlyph) { - currentPos.x += renderGlyph(currentPos, c); + // render glyph + else { + // render online if is visible on screen + if(currentPos.x < screenSize.width()) + currentPos.x += renderGlyph(currentPos, c); } } - // end font render - glEnd(); + // end texture redering + g_graphics._endTextureRender(); + g_graphics.resetColor(); } int Font::renderGlyph(const Point& pos, int glyph) { - // get glyph width - int glyphWidth = m_glyphWidths[glyph]; - - // calculate glyph coords on texture font - const Size& textureSize = m_texture->getSize(); - int glyphTexCoordX = ((glyph - m_firstGlyph) % m_numHorizontalGlyphs) * m_glyphSize.width(); - int glyphTexCoordY = ((glyph - m_firstGlyph) / m_numHorizontalGlyphs) * m_glyphSize.height(); - float textureRight = (float)(glyphTexCoordX + glyphWidth) / textureSize.width(); - float textureBottom = (float)(glyphTexCoordY + m_glyphSize.height()) / textureSize.height(); - float textureTop = (float)(glyphTexCoordY) / textureSize.height(); - float textureLeft = (float)(glyphTexCoordX) / textureSize.width(); - - // calculate glyph coords on screen - int right = pos.x + glyphWidth; - int bottom = pos.y + m_glyphSize.height(); - int top = pos.y; - int left = pos.x; + // don't render invalid glyphs + if(glyph < 32) + return 0; // render glyph - glTexCoord2f(textureLeft, textureTop); glVertex2i(left, top); - glTexCoord2f(textureLeft, textureBottom); glVertex2i(left, bottom); - glTexCoord2f(textureRight, textureBottom); glVertex2i(right, bottom); - glTexCoord2f(textureRight, textureTop); glVertex2i(right, top); + Rect screenCoords(pos, m_glyphsSize[glyph]); + g_graphics._drawTexturedRect(screenCoords, m_glyphsTextureCoords[glyph], m_texture->getSize()); - return glyphWidth; + return m_glyphsSize[glyph].width(); } diff --git a/src/framework/font.h b/src/framework/font.h index 81757841..29b2aed3 100644 --- a/src/framework/font.h +++ b/src/framework/font.h @@ -28,6 +28,7 @@ #include "prerequisites.h" #include "color.h" #include "texture.h" +#include "rect.h" class Font { @@ -67,11 +68,8 @@ private: int m_cursorSize; Color m_color; TexturePtr m_texture; - Size m_textureSize; - Size m_glyphSize; - int m_firstGlyph; - int m_glyphWidths[256]; - int m_numHorizontalGlyphs; + Rect m_glyphsTextureCoords[256]; + Size m_glyphsSize[256]; }; #endif // FONT_H diff --git a/src/framework/graphics.cpp b/src/framework/graphics.cpp index 724179d0..689ff52d 100644 --- a/src/framework/graphics.cpp +++ b/src/framework/graphics.cpp @@ -125,7 +125,37 @@ void Graphics::endRender() } + +void Graphics::setColor(const Color& color) +{ + glColor4ubv(color.rgbaPtr()); +} + +void Graphics::resetColor() +{ + glColor4ub(0xFF, 0xFF, 0xFF, 0xFF); +} + +void Graphics::_beginTextureRender(const Texture *texture) +{ + glBindTexture(GL_TEXTURE_2D, texture->getTextureId()); + glBegin(GL_QUADS); +} + +void Graphics::_endTextureRender() +{ + glEnd(); +} + void Graphics::drawTexturedRect(const Rect& screenCoords, const Texture *texture, const Rect& textureCoords) +{ + glBindTexture(GL_TEXTURE_2D, texture->getTextureId()); + glBegin(GL_QUADS); + _drawTexturedRect(screenCoords, textureCoords, texture->getSize()); + glEnd(); +} + +void Graphics::_drawTexturedRect(const Rect& screenCoords, const Rect& textureCoords, const Size& textureSize) { // rect correction for opengl int right = screenCoords.right() + 1; @@ -139,20 +169,16 @@ void Graphics::drawTexturedRect(const Rect& screenCoords, const Texture *texture float textureLeft = 1.0f; if(!textureCoords.isEmpty()) { - const Size& textureSize = texture->getSize(); textureRight = (float)(textureCoords.right() + 1) / textureSize.width(); textureBottom = (float)(textureCoords.bottom() + 1) / textureSize.height(); textureTop = (float)textureCoords.top() / textureSize.height(); textureLeft = (float)textureCoords.left() / textureSize.width(); } - glBindTexture(GL_TEXTURE_2D, texture->getTextureId()); - glBegin(GL_QUADS); - glTexCoord2f(textureLeft, textureTop); glVertex2i(left, top); - glTexCoord2f(textureLeft, textureBottom); glVertex2i(left, bottom); - glTexCoord2f(textureRight, textureBottom); glVertex2i(right, bottom); - glTexCoord2f(textureRight, textureTop); glVertex2i(right, top); - glEnd(); + glTexCoord2f(textureLeft, textureTop); glVertex2i(left, top); + glTexCoord2f(textureLeft, textureBottom); glVertex2i(left, bottom); + glTexCoord2f(textureRight, textureBottom); glVertex2i(right, bottom); + glTexCoord2f(textureRight, textureTop); glVertex2i(right, top); } void Graphics::drawColoredRect(const Rect& screenCoords, const Color& color) diff --git a/src/framework/graphics.h b/src/framework/graphics.h index 1030baed..c192b2a6 100644 --- a/src/framework/graphics.h +++ b/src/framework/graphics.h @@ -57,10 +57,19 @@ public: const Size& getScreenSize() const { return m_screenSize; } + void setColor(const Color& color); + void resetColor(); + + // high level rendering void drawTexturedRect(const Rect& screenCoords, const Texture *texture, const Rect& texCoords = Rect()); void drawColoredRect(const Rect& screenCoords, const Color& color); void drawBoundingRect(const Rect& screenCoords, const Color& color, int innerLineWidth); + // lower level rendering + void _beginTextureRender(const Texture *texture); + void _drawTexturedRect(const Rect& screenCoords, const Rect& textureCoords, const Size& textureSize); + void _endTextureRender(); + private: Size m_screenSize; }; diff --git a/src/framework/rect.h b/src/framework/rect.h index 065f92a2..ab78e222 100644 --- a/src/framework/rect.h +++ b/src/framework/rect.h @@ -44,7 +44,7 @@ public: inline TRect(const TPoint& topLeft, const TPoint& bottomRight) : x1(topLeft.x), y1(topLeft.y), x2(bottomRight.x), y2(bottomRight.y) { } inline TRect(const TRect& other) : x1(other.x1), y1(other.y1), x2(other.x2), y2(other.y2) { } inline TRect(T x, T y, const TSize& size) : x1(x), y1(y), x2(x+size.width()-1), y2(y+size.height()-1) { } - inline TRect(const TPoint& topLeft, const TSize& size) : x1(topLeft.x), y1(topLeft.y), x2(x+size.width()-1), y2(y+size.height()-1) { } + inline TRect(const TPoint& topLeft, const TSize& size) : x1(topLeft.x), y1(topLeft.y), x2(x1+size.width()-1), y2(y1+size.height()-1) { } inline bool isNull() const { return x2 == x1 - 1 && y2 == y1 - 1; } inline bool isEmpty() const { return x1 > x2 || y1 > y2; }