Code:
void Text::preRender() {
const std::string &data = /*...*/;
if(data.empty()) {
texture = -1;
return;
}
SDL_Color c = /*...*/;
TTF_Font *font = /*...*/;
// note: we rely on this function creating 32-bit images,
// as its documentation describes.
SDL_Surface *first = TTF_RenderText_Blended(font, data.c_str(), c);
int w = nextPowerOf2(first->w);
int h = nextPowerOf2(first->h);
// save the ratio between rendered text and actual texture dimensions
this->widthFactor = double(w) / first->w;
this->heightFactor = double(h) / first->h;
SDL_Surface *second = SDL_CreateRGBSurface(
SDL_SWSURFACE, w, h,
32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
// copy data from first to second, translating to new format
SDL_BlitSurface(first, NULL, second, NULL);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// we assume this copies the pixels from second, and later free second
glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_BGRA,
GL_UNSIGNED_BYTE, second->pixels);
glDisable(GL_TEXTURE_2D);
SDL_FreeSurface(first);
SDL_FreeSurface(second);
dirty = false;
}
void Text::render() {
if(dirty) {
preRender();
}
if(texture == unsigned(-1)) {
return; // empty text, or error in pre-rendering
}
WidgetPoint corner = getBoundingRect().getCorner();
WidgetPoint dimensions = getBoundingRect().getDimensions();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glColor3f(1.0f, 1.0f, 1.0f);
// comment this out to disable font transparency
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR);
glBegin(GL_QUADS);
double width = dimensions.getX() * widthFactor;
double height = dimensions.getY() * heightFactor;
// scale dimensions to take the larger power-of-2 texture into account
// this way it looks the same no matter how big the texture actually is
WidgetPoint topLeft = corner;
WidgetPoint lowerLeft = corner;
WidgetPoint topRight = corner;
WidgetPoint lowerRight = corner;
lowerLeft.addY(height);
lowerRight.addY(height);
topRight.addX(width);
lowerRight.addX(width);
glTexCoord2i(0, 0); WidgetRenderer::glVertex(topLeft);
glTexCoord2i(1, 0); WidgetRenderer::glVertex(topRight);
glTexCoord2i(1, 1); WidgetRenderer::glVertex(lowerRight);
glTexCoord2i(0, 1); WidgetRenderer::glVertex(lowerLeft);
glEnd();
// back to "normal" blending
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
}
Hope that's at least a little bit understandable . . . .