mirror of
https://github.com/wesnoth/wesnoth
synced 2024-09-20 07:51:33 +00:00
200 lines
4.2 KiB
C++
200 lines
4.2 KiB
C++
/* $Id$ */
|
|
/*
|
|
Copyright (C) 2003 by David White <davidnwhite@optusnet.com.au>
|
|
Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License.
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY.
|
|
|
|
See the COPYING file for more details.
|
|
*/
|
|
#include "config.hpp"
|
|
#include "font.hpp"
|
|
#include "SDL_ttf.h"
|
|
|
|
#include <cstdio>
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <sstream>
|
|
#include <string>
|
|
|
|
namespace {
|
|
|
|
std::map<int,TTF_Font*> font_table;
|
|
|
|
//SDL_ttf seems to have a problem where TTF_OpenFont will seg fault if
|
|
//the font file doesn't exist, so make sure it exists first.
|
|
TTF_Font* open_font(const std::string& fname, int size)
|
|
{
|
|
if(read_file(fname).empty())
|
|
return NULL;
|
|
|
|
return TTF_OpenFont(fname.c_str(),size);
|
|
}
|
|
|
|
TTF_Font* get_font(int size)
|
|
{
|
|
const std::map<int,TTF_Font*>::iterator it = font_table.find(size);
|
|
if(it != font_table.end())
|
|
return it->second;
|
|
|
|
TTF_Font* font = NULL;
|
|
std::cerr << "opening font file...\n";
|
|
|
|
#ifdef WESNOTH_PATH
|
|
font = open_font(std::string(WESNOTH_PATH) + "/images/misc/Vera.ttf",size);
|
|
#endif
|
|
|
|
if(font == NULL) {
|
|
font = open_font("images/misc/Vera.ttf",size);
|
|
}
|
|
|
|
if(font == NULL) {
|
|
std::cerr << "Could not open font file\n";
|
|
return font;
|
|
}
|
|
|
|
TTF_SetFontStyle(font,TTF_STYLE_NORMAL);
|
|
|
|
std::cerr << "inserting font...\n";
|
|
font_table.insert(std::pair<int,TTF_Font*>(size,font));
|
|
return font;
|
|
}
|
|
|
|
}
|
|
|
|
namespace font {
|
|
|
|
manager::manager()
|
|
{
|
|
const int res = TTF_Init();
|
|
if(res < 0) {
|
|
std::cerr << "Could not initialize true type fonts\n";
|
|
} else {
|
|
std::cerr << "Initialized true type fonts\n";
|
|
}
|
|
}
|
|
|
|
manager::~manager()
|
|
{
|
|
for(std::map<int,TTF_Font*>::iterator i = font_table.begin();
|
|
i != font_table.end(); ++i) {
|
|
TTF_CloseFont(i->second);
|
|
}
|
|
|
|
TTF_Quit();
|
|
}
|
|
|
|
SDL_Rect draw_text_line(display* gui, const SDL_Rect& area, int size,
|
|
COLOUR colour, const std::string& text, int x, int y,
|
|
SDL_Surface* bg)
|
|
{
|
|
static const SDL_Color colours[] =
|
|
// neutral good bad
|
|
{ {0xFF,0xFF,0,0}, {0,0xFF,0,0}, {0xFF,0,0,0} };
|
|
|
|
const SDL_Color& col = colours[colour];
|
|
TTF_Font* const font = get_font(size);
|
|
if(font == NULL) {
|
|
std::cerr << "Could not get font\n";
|
|
SDL_Rect res;
|
|
res.x = 0; res.y = 0; res.w = 0; res.h = 0;
|
|
return res;
|
|
}
|
|
|
|
SDL_Surface* const surface = TTF_RenderText_Blended(font,text.c_str(),col);
|
|
if(surface == NULL) {
|
|
std::cerr << "Could not render ttf: '" << text << "'\n";
|
|
SDL_Rect res;
|
|
res.x = 0; res.y = 0; res.w = 0; res.h = 0;
|
|
return res;
|
|
}
|
|
|
|
SDL_Rect dest;
|
|
dest.x = x;
|
|
dest.y = y;
|
|
dest.w = surface->w;
|
|
dest.h = surface->h;
|
|
|
|
if(dest.x + dest.w > area.x + area.w) {
|
|
dest.w = area.x + area.w - dest.x;
|
|
}
|
|
|
|
if(dest.y + dest.h > area.y + area.h) {
|
|
dest.h = area.y + area.h - dest.y;
|
|
}
|
|
|
|
if(gui != NULL) {
|
|
SDL_Rect src = dest;
|
|
src.x = 0;
|
|
src.y = 0;
|
|
SDL_BlitSurface(surface,&src,gui->video().getSurface(),&dest);
|
|
}
|
|
|
|
SDL_FreeSurface(surface);
|
|
|
|
return dest;
|
|
}
|
|
|
|
|
|
SDL_Rect draw_text(display* gui, const SDL_Rect& area, int size,
|
|
COLOUR colour, const std::string& txt, int x, int y,
|
|
SDL_Surface* bg)
|
|
{
|
|
//make sure there's always at least a space, so we can ensure
|
|
//that we can return a rectangle for height
|
|
static const std::string blank_text(" ");
|
|
const std::string& text = txt.empty() ? blank_text : txt;
|
|
|
|
SDL_Rect res;
|
|
res.x = x;
|
|
res.y = y;
|
|
res.w = 0;
|
|
res.h = 0;
|
|
|
|
std::string::const_iterator i1 = text.begin();
|
|
std::string::const_iterator i2 = std::find(i1,text.end(),'\n');
|
|
for(;;) {
|
|
if(i1 != i2) {
|
|
COLOUR col = NORMAL_COLOUR;
|
|
int sz = size;
|
|
if(*i1 == '#') {
|
|
col = BAD_COLOUR;
|
|
++i1;
|
|
} else if(*i1 == '@') {
|
|
col = GOOD_COLOUR;
|
|
++i1;
|
|
} else if(*i1 == '+') {
|
|
sz += 2;
|
|
++i1;
|
|
} else if(*i1 == '-') {
|
|
sz -= 2;
|
|
++i1;
|
|
}
|
|
|
|
if(i1 != i2) {
|
|
const std::string new_string(i1,i2);
|
|
const SDL_Rect rect =
|
|
draw_text_line(gui,area,sz,col,new_string,x,y,bg);
|
|
if(rect.w > res.w)
|
|
res.w = rect.w;
|
|
res.h += rect.h;
|
|
y += rect.h;
|
|
}
|
|
}
|
|
|
|
if(i2 == text.end()) {
|
|
break;
|
|
}
|
|
|
|
i1 = i2+1;
|
|
i2 = std::find(i1,text.end(),'\n');
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
}
|