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