00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <vector>
00024
00025
00026
00027
00028 #include <boost/filesystem/convenience.hpp>
00029
00030
00031
00032
00033
00034 #include "util/structures/rect.h"
00035 #include "util/base/exception.h"
00036 #include "util/utf8/utf8.h"
00037 #include "video/image.h"
00038 #include "video/renderbackend.h"
00039
00040 #include "fontbase.h"
00041
00042 namespace FIFE {
00043
00044 FontBase::FontBase():
00045 m_pool(),
00046 mColor(),
00047 mGlyphSpacing(0),
00048 mRowSpacing(0),
00049 mFilename(""),
00050 m_antiAlias(true) {
00051 }
00052
00053 void FontBase::setRowSpacing(int spacing) {
00054 mRowSpacing = spacing;
00055 }
00056
00057 int FontBase::getRowSpacing() const {
00058 return mRowSpacing;
00059 }
00060
00061 void FontBase::setGlyphSpacing(int spacing) {
00062 mGlyphSpacing = spacing;
00063 }
00064
00065 int FontBase::getGlyphSpacing() const {
00066 return mGlyphSpacing;
00067 }
00068
00069 void FontBase::setAntiAlias(bool antiAlias) {
00070 m_antiAlias = antiAlias;
00071 }
00072
00073 bool FontBase::isAntiAlias() {
00074 return m_antiAlias;
00075 }
00076
00077 SDL_Color FontBase::getColor() const {
00078 return mColor;
00079 }
00080
00081 int FontBase::getStringIndexAt(const std::string &text, int x) const {
00082 assert( utf8::is_valid(text.begin(), text.end()) );
00083 std::string::const_iterator cur;
00084 if (text.size() == 0) return 0;
00085 if (x <= 0) return 0;
00086
00087 cur = text.begin();
00088
00089 utf8::next(cur, text.end());
00090
00091 std::string buff;
00092 while(cur != text.end()) {
00093 buff = std::string(text.begin(), cur);
00094
00095 if (getWidth(buff) > x) {
00096 return buff.size();
00097 } else {
00098 utf8::next(cur, text.end());
00099 }
00100 }
00101
00102 if (x > getWidth(text)) {
00103 return text.size();
00104 } else {
00105 return buff.size();
00106 }
00107 }
00108
00109 Image* FontBase::getAsImage(const std::string& text) {
00110 Image* image = m_pool.getRenderedText(this, text);
00111 if (!image) {
00112 SDL_Surface* textSurface = renderString(text);
00113 image = RenderBackend::instance()->createImage(textSurface);
00114 m_pool.addRenderedText( this, text, image );
00115 }
00116 return image;
00117 }
00118
00119 Image* FontBase::getAsImageMultiline(const std::string& text) {
00120 const uint8_t newline_utf8 = '\n';
00121 uint32_t newline;
00122 utf8::utf8to32(&newline_utf8,&newline_utf8 + 1,&newline);
00123
00124 Image* image = m_pool.getRenderedText(this, text);
00125 if (!image) {
00126 std::vector<SDL_Surface*> lines;
00127 std::string::const_iterator it = text.begin();
00128
00129 int render_width = 0, render_height = 0;
00130 do {
00131 uint32_t codepoint = 0;
00132 std::string line;
00133 while( codepoint != newline && it != text.end() )
00134 {
00135 codepoint = utf8::next(it,text.end());
00136 if( codepoint != newline )
00137 utf8::append(codepoint, back_inserter(line));
00138 }
00139
00140 SDL_Surface* text_surface = renderString(line);
00141 if (text_surface->w > render_width) {
00142 render_width = text_surface->w;
00143 }
00144 lines.push_back(text_surface);
00145 } while (it != text.end());
00146
00147 render_height = (getRowSpacing() + getHeight()) * lines.size();
00148 SDL_Surface* final_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
00149 render_width,render_height,32,
00150 RMASK, GMASK, BMASK ,AMASK);
00151 if (!final_surface) {
00152 throw SDLException(std::string("CreateRGBSurface failed: ") + SDL_GetError());
00153 }
00154 SDL_FillRect(final_surface, 0, 0x00000000);
00155 int ypos = 0;
00156 for (std::vector<SDL_Surface*>::iterator i = lines.begin(); i != lines.end(); ++i) {
00157 SDL_Rect dst_rect = { 0, 0, 0, 0 };
00158 dst_rect.y = ypos;
00159
00160 SDL_SetAlpha(*i,0,SDL_ALPHA_OPAQUE);
00161 SDL_BlitSurface(*i,0,final_surface,&dst_rect);
00162 ypos += getRowSpacing() + getHeight();
00163 SDL_FreeSurface(*i);
00164 }
00165 image = RenderBackend::instance()->createImage(final_surface);
00166 m_pool.addRenderedText(this, text, image);
00167 }
00168 return image;
00169 }
00170
00171 std::string FontBase::splitTextToWidth (const std::string& text, int render_width) {
00172 const uint32_t whitespace = ' ';
00173 const uint8_t newline_utf8 = '\n';
00174 uint32_t newline;
00175 utf8::utf8to32(&newline_utf8,&newline_utf8 + 1,&newline);
00176 if (render_width <= 0 || text.empty()) {
00177 return text;
00178 }
00179 std::string output;
00180 std::string line;
00181 std::string::const_iterator pos = text.begin();
00182 std::list<std::pair<size_t,std::string::const_iterator> > break_pos;
00183 bool firstLine = true;
00184
00185 while( pos != text.end())
00186 {
00187 break_pos.clear();
00188 if( !firstLine ) {
00189 line = "\n";
00190 } else {
00191 firstLine = false;
00192 }
00193
00194 bool haveNewLine = false;
00195 while( getWidth(line) < render_width && pos != text.end() )
00196 {
00197 uint32_t codepoint = utf8::next(pos, text.end());
00198 if (codepoint == whitespace && !line.empty())
00199 break_pos.push_back( std::make_pair(line.length(),pos) );
00200
00201 if( codepoint != newline )
00202 utf8::append(codepoint, back_inserter(line) );
00203
00204
00205 if( codepoint == newline ) {
00206 output.append(line);
00207 line = "";
00208 haveNewLine = true;
00209 break;
00210 }
00211 }
00212 if( haveNewLine )
00213 continue;
00214
00215 if( pos == text.end() )
00216 break;
00217
00218 if( break_pos.empty() ) {
00219
00220
00221
00222 if( utf8::distance(line.begin(),line.end()) <= 1 && line != "\n") {
00223 output.append(line);
00224 continue;
00225 }
00226
00227 if (line == "\n") {
00228 ++pos;
00229 }
00230
00231
00232
00233
00234
00235
00236 } else {
00237 line = line.substr(0,break_pos.back().first);
00238 pos = break_pos.back().second;
00239 }
00240 output.append(line);
00241 }
00242 if( !line.empty() ) {
00243 output.append(line);
00244 }
00245 return output;
00246 }
00247 }