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