00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <guichan/exception.hpp>
00023
00024 #include "truetypefont.h"
00025
00026 #include "../graphics.h"
00027 #include "../resources/image.h"
00028
00029 #define CACHE_SIZE 256
00030
00031 class TextChunk
00032 {
00033 public:
00034 TextChunk(const std::string &text, const gcn::Color &color) :
00035 img(NULL), text(text), color(color)
00036 {
00037 }
00038
00039 ~TextChunk()
00040 {
00041 delete img;
00042 }
00043
00044 bool operator==(const TextChunk &chunk) const
00045 {
00046 return (chunk.text == text && chunk.color == color);
00047 }
00048
00049 void generate(TTF_Font *font)
00050 {
00051 SDL_Color sdlCol;
00052 sdlCol.b = color.b;
00053 sdlCol.r = color.r;
00054 sdlCol.g = color.g;
00055
00056 SDL_Surface *surface = TTF_RenderUTF8_Blended(
00057 font, text.c_str(), sdlCol);
00058
00059 if (!surface)
00060 {
00061 throw "Rendering font to surface failed: " +
00062 std::string(TTF_GetError());
00063 }
00064
00065 img = Image::load(surface);
00066
00067 SDL_FreeSurface(surface);
00068 }
00069
00070 Image *img;
00071 std::string text;
00072 gcn::Color color;
00073 };
00074
00075 typedef std::list<TextChunk>::iterator CacheIterator;
00076
00077 static int fontCounter;
00078
00079 TrueTypeFont::TrueTypeFont(const std::string &filename, int size, int style)
00080 {
00081 if (fontCounter == 0 && TTF_Init() == -1)
00082 {
00083 throw GCN_EXCEPTION("Unable to initialize SDL_ttf: " +
00084 std::string(TTF_GetError()));
00085 }
00086
00087 ++fontCounter;
00088 mFont = TTF_OpenFont(filename.c_str(), size);
00089
00090 if (!mFont)
00091 {
00092 throw GCN_EXCEPTION("SDLTrueTypeFont::SDLTrueTypeFont: " +
00093 std::string(TTF_GetError()));
00094 }
00095
00096 TTF_SetFontStyle(mFont, style);
00097 }
00098
00099 TrueTypeFont::~TrueTypeFont()
00100 {
00101 TTF_CloseFont(mFont);
00102 --fontCounter;
00103
00104 if (fontCounter == 0)
00105 {
00106 TTF_Quit();
00107 }
00108 }
00109
00110 void TrueTypeFont::drawString(gcn::Graphics *graphics,
00111 const std::string &text,
00112 int x, int y)
00113 {
00114 if (text.empty())
00115 return;
00116
00117 Graphics *g = dynamic_cast<Graphics *>(graphics);
00118
00119 if (!g)
00120 {
00121 throw "Not a valid graphics object!";
00122 }
00123
00124 gcn::Color col = g->getColor();
00125 const float alpha = col.a / 255.0f;
00126
00127
00128
00129
00130 col.a = 255;
00131
00132 TextChunk chunk(text, col);
00133
00134 bool found = false;
00135
00136 for (CacheIterator i = mCache.begin(); i != mCache.end(); ++i)
00137 {
00138 if (chunk == (*i))
00139 {
00140
00141 mCache.splice(mCache.begin(), mCache, i);
00142 found = true;
00143 break;
00144 }
00145 }
00146
00147
00148 if (!found)
00149 {
00150 if (mCache.size() >= CACHE_SIZE)
00151 {
00152 mCache.pop_back();
00153 }
00154 mCache.push_front(chunk);
00155 mCache.front().generate(mFont);
00156 }
00157
00158 mCache.front().img->setAlpha(alpha);
00159 g->drawImage(mCache.front().img, x, y);
00160 }
00161
00162 int TrueTypeFont::getWidth(const std::string &text) const
00163 {
00164 int w, h;
00165 TTF_SizeUTF8(mFont, text.c_str(), &w, &h);
00166 return w;
00167 }
00168
00169 int TrueTypeFont::getHeight() const
00170 {
00171 return TTF_FontHeight(mFont);
00172 }