advanced text render

master
Eduardo Bart 13 years ago
parent 8d1281b316
commit f3df212793

@ -102,62 +102,119 @@ bool Font::load(const std::string& file)
}
void Font::renderText(const Point& pos, const std::string& text)
{
Size boxSize = g_graphics.getScreenSize() - pos.toSize();
Rect screenCoords(pos, boxSize);
Font::renderText(screenCoords, text);
}
void Font::renderText(const Rect& screenCoords, const std::string& text, const Point& startRenderPosition, bool debug)
{
// begin texture rendering
g_graphics.setColor(m_color);
g_graphics._beginTextureRender(m_texture.get());
Point currentPos = pos;
const Size& screenSize = g_graphics.getScreenSize();
const Size& textureSize = m_texture->getSize();
int textLenght = text.length();
// map glyphs positions
Point *glyphsPositions = mapGlyphsPositions(text);
for(int i = 0; i < textLenght; ++i) {
int glyph = (int)text[i];
// break rendering if the Y pos is below the screen
if(currentPos.y >= screenSize.height())
break;
// skip invalid glyphs
if(glyph < 32)
continue;
// new line
if(glyph == (uchar)'\n') {
currentPos.y += m_lineHeight;
currentPos.x = pos.x;
// calculate virtual glyph rect
Rect glyphScreenCoords(glyphsPositions[i], m_glyphsSize[glyph]);
Rect glyphTextureCoords = m_glyphsTextureCoords[glyph];
// only render glyphs that is visible after startRenderPosition
if(glyphScreenCoords.bottom() < startRenderPosition.y || glyphScreenCoords.right() < startRenderPosition.x)
continue;
// bound glyph topLeft to startRenderPosition
if(glyphScreenCoords.top() < startRenderPosition.y) {
glyphTextureCoords.setTop(glyphTextureCoords.top() + (startRenderPosition.y - glyphScreenCoords.top()));
glyphScreenCoords.setTop(startRenderPosition.y);
}
// render only if the glyph is valid and visible
else if(glyph >= 32 && currentPos.x < screenSize.width()) {
g_graphics._drawTexturedRect(Rect(currentPos, m_glyphsSize[glyph]),
m_glyphsTextureCoords[glyph],
textureSize);
currentPos.x += m_glyphsSize[glyph].width();
if(glyphScreenCoords.left() < startRenderPosition.x) {
glyphTextureCoords.setLeft(glyphTextureCoords.left() + (startRenderPosition.x - glyphScreenCoords.left()));
glyphScreenCoords.setLeft(startRenderPosition.x);
}
// translate glyph
glyphScreenCoords.translate(-startRenderPosition);
glyphScreenCoords.translate(screenCoords.topLeft());
// only render if glyph rect is visible on screenCoords
if(!screenCoords.intersects(glyphScreenCoords))
continue;
// bound glyph bottomRight to screenCoords bottomRight
if(glyphScreenCoords.bottom() > screenCoords.bottom()) {
glyphTextureCoords.setBottom(glyphTextureCoords.bottom() + (screenCoords.bottom() - glyphScreenCoords.bottom()));
glyphScreenCoords.setBottom(screenCoords.bottom());
}
if(glyphScreenCoords.right() > screenCoords.right()) {
glyphTextureCoords.setRight(glyphTextureCoords.right() + (screenCoords.right() - glyphScreenCoords.right()));
glyphScreenCoords.setRight(screenCoords.right());
}
// render glyph
g_graphics._drawTexturedRect(glyphScreenCoords, glyphTextureCoords, textureSize);
}
// end texture redering
g_graphics._endTextureRender();
g_graphics.resetColor();
// debug box
//g_graphics.drawBoundingRect(Rect(pos, calculateTextSize(text)).expanded(1), Color(0xFF00FF00), 1);
if(debug)
g_graphics.drawBoundingRect(screenCoords.expanded(1), Color(0xFF00FF00), 1);
}
Size Font::calculateTextSize(const std::string& text)
Size Font::calculateTextSize(const std::string& text, Point *glyphsPositions)
{
int textLenght = text.length();
if(!glyphsPositions) {
glyphsPositions = mapGlyphsPositions(text);
}
Size size;
Point currentPos(0,m_lineHeight);
int numGlyphs = text.length();
for(int i = 0; i < numGlyphs; ++i) {
Point bottomLeft = glyphsPositions[i] + m_glyphsSize[(int)text[i]].toPoint();
size = size.expandedTo(bottomLeft.toSize());
}
return size;
}
for(int i = 0; i < textLenght; ++i) {
Point* Font::mapGlyphsPositions(const std::string& text)
{
static Point glyphsPositions[8192];
int numGlyphs = text.length();
Point virtualPos;
if(numGlyphs > 8192)
logFatal("A text was too long to render!");
for(int i = 0; i < numGlyphs; ++i) {
int glyph = (int)text[i];
// store current glyph topLeft
glyphsPositions[i] = virtualPos;
// new line
if(glyph == (uchar)'\n') {
currentPos.y += m_lineHeight;
currentPos.x = 0;
virtualPos.y += m_lineHeight;
virtualPos.x = 0;
}
// render only if the glyph is valid
else if(glyph >= 32) {
currentPos.x += m_glyphsSize[glyph].width();
virtualPos.x += m_glyphsSize[glyph].width();
}
size = size.expandedTo(currentPos.toSize());
}
return size;
return (Point *)glyphsPositions;
}

@ -42,18 +42,16 @@ public:
/// Simple text render starting at pos
void renderText(const Point& pos, const std::string& text);
/// Render text delimited by screenCoords rect
void renderText(const Rect& screenCoords, const std::string& text);
/** Advanced text render
* screenCoords is the rect that will be filled on the screen
* startRenderPosition is the postion to start rendering relative to the text rect
*/
void renderText(const Rect& screenCoords, const Point& startRenderPosition, const std::string& text);
void renderText(const Rect& screenCoords, const std::string& text, const Point& startRenderPosition = Point(), bool debug = false);
/// Simulate render and calculate text size
Size calculateTextSize(const std::string& text);
Size calculateTextSize(const std::string& text, Point *glyphsPositions = NULL);
Point *mapGlyphsPositions(const std::string& text);
/*
enum EAlign {
ALIGN_TOP = 1 << 0,

@ -96,15 +96,15 @@ public:
inline void moveBottomLeft(const TPoint<T> &p) { moveLeft(p.x); moveBottom(p.y); }
inline TRect<T> translated(int x, int y) const { return TRect<T>(TPoint<T>(x1 + x, y1 + y), TPoint<T>(x2 + x, y2 + y)); }
inline TRect<T> translated(const TPoint<T> &p) const { return TRect<T>(TPoint<T>(x1 + p.x(), y1 + p.y()), TPoint<T>(x2 + p.x(), y2 + p.y())); }
inline TRect<T> translated(const TPoint<T> &p) const { return TRect<T>(TPoint<T>(x1 + p.x, y1 + p.y), TPoint<T>(x2 + p.x, y2 + p.y)); }
inline TRect<T> expanded(T pixels) { return TRect<T>(TPoint<T>(x1 - pixels, y1 - pixels), TPoint<T>(x2 + pixels, y2 + pixels)); }
inline TRect<T> expanded(T pixels) const { return TRect<T>(TPoint<T>(x1 - pixels, y1 - pixels), TPoint<T>(x2 + pixels, y2 + pixels)); }
inline void moveCenter(const TPoint<T> &p) {
T w = x2 - x1;
T h = y2 - y1;
x1 = p.x() - w/2;
y1 = p.y() - h/2;
x1 = p.x - w/2;
y1 = p.y - h/2;
x2 = x1 + w;
y2 = y1 + h;
}
@ -119,10 +119,10 @@ public:
r = x2;
}
if(insideOnly) {
if(p.x() <= l || p.x() >= r)
if(p.x <= l || p.x >= r)
return false;
} else {
if(p.x() < l || p.x() > r)
if(p.x < l || p.x > r)
return false;
}
int t, b;
@ -134,10 +134,10 @@ public:
b = y2;
}
if(insideOnly) {
if(p.y() <= t || p.y() >= b)
if(p.y <= t || p.y >= b)
return false;
} else {
if(p.y() < t || p.y() > b)
if(p.y < t || p.y > b)
return false;
}
return true;

@ -101,7 +101,7 @@ int main(int argc, const char *argv[])
640, 480,
g_configs.getBoolean("window maximized"));
Platform::setWindowTitle("OTClient");
//Platform::setVsync();
Platform::setVsync();
// init engine
g_engine.init();

@ -30,6 +30,7 @@
#include "framework/engine.h"
#include "framework/rect.h"
#include "framework/fonts.h"
#include "framework/input.h"
TexturePtr background;
@ -49,8 +50,24 @@ void MenuState::onClose()
g_engine.stop();
}
int x, y;
void MenuState::onInputEvent(InputEvent* event)
{
static bool moving = false;
static int lastX;
static int lastY;
if(event->type == EV_MOUSE_LDOWN) {
moving = true;
lastX = event->mouse.x;
lastY = event->mouse.y;
} else if(event->type == EV_MOUSE_LUP) {
moving = false;
} else if(event->type == EV_MOUSE_MOVE) {
if(moving) {
x = lastX - event->mouse.x;
y = lastY - event->mouse.y;
}
}
}
void MenuState::render()
@ -67,9 +84,15 @@ void MenuState::render()
Rect texCoords(0, 0, texCoordsSize);
texCoords.moveBottomRight(texSize.toPoint());
g_graphics.drawTexturedRect(Rect(0, 0, screenSize), m_background.get(), texCoords);
g_defaultFont->renderText(Point(10,screenSize.height() - 50), "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n"
"Sed blandit justo in lectus ornare ultricies.\n"
"Integer faucibus magna quis metus fermentum suscipit.");
static const char *text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n"
"Nulla pulvinar odio ac arcu tempor consequat.\n"
"Praesent at enim sapien, at vestibulum ligula.\n"
"Aliquam eleifend ante eu sapien vehicula consectetur.\n"
"Nunc id ligula ligula, eget vestibulum magna.\n"
"In mattis nisi non nisl semper ultricies.\n";
Size textSize = g_defaultFont->calculateTextSize(text);
g_defaultFont->renderText(Rect(100, 100, textSize.width() - 120, textSize.height() - 15), text, Point(x,y), true);
}
void MenuState::update(int ticks, int elapsedTicks)

Loading…
Cancel
Save