FIFE  2008.0
 All Classes Namespaces Functions Variables Enumerations Enumerator Pages
fontbase.cpp
1 /***************************************************************************
2  * Copyright (C) 2005-2008 by the FIFE team *
3  * http://www.fifengine.de *
4  * This file is part of FIFE. *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 #include <vector>
24 
25 // Platform specific includes
26 
27 // 3rd party library includes
28 
29 // FIFE includes
30 // These includes are split up in two parts, separated by one empty line
31 // First block: files included from the FIFE root src directory
32 // Second block: files included from the same folder
33 #include "util/structures/rect.h"
34 #include "util/base/exception.h"
35 #include "util/utf8/utf8.h"
36 #include "video/image.h"
37 #include "video/renderbackend.h"
38 
39 #include "fontbase.h"
40 
41 namespace FIFE {
42 
43  FontBase::FontBase():
44  m_pool(),
45  mColor(),
46  mGlyphSpacing(0),
47  mRowSpacing(0),
48  mFilename(""),
49  m_antiAlias(true) {
50  }
51 
52  void FontBase::invalidate() {
53  m_pool.invalidateCachedText();
54  }
55 
56  void FontBase::setRowSpacing(int32_t spacing) {
57  mRowSpacing = spacing;
58  }
59 
60  int32_t FontBase::getRowSpacing() const {
61  return mRowSpacing;
62  }
63 
64  void FontBase::setGlyphSpacing(int32_t spacing) {
65  mGlyphSpacing = spacing;
66  }
67 
68  int32_t FontBase::getGlyphSpacing() const {
69  return mGlyphSpacing;
70  }
71 
72  void FontBase::setAntiAlias(bool antiAlias) {
73  m_antiAlias = antiAlias;
74  }
75 
77  return m_antiAlias;
78  }
79 
80  SDL_Color FontBase::getColor() const {
81  return mColor;
82  }
83 
84  int32_t FontBase::getStringIndexAt(const std::string &text, int32_t x) const {
85  assert( utf8::is_valid(text.begin(), text.end()) );
86  std::string::const_iterator cur;
87  if (text.size() == 0) return 0;
88  if (x <= 0) return 0;
89 
90  cur = text.begin();
91 
92  utf8::next(cur, text.end());
93 
94  std::string buff;
95  while(cur != text.end()) {
96  buff = std::string(text.begin(), cur);
97 
98  if (getWidth(buff) > x) {
99  return buff.size();
100  } else {
101  utf8::next(cur, text.end());
102  }
103  }
104 
105  if (x > getWidth(text)) {
106  return text.size();
107  } else {
108  return buff.size();
109  }
110  }
111 
112  Image* FontBase::getAsImage(const std::string& text) {
113  Image* image = m_pool.getRenderedText(this, text);
114  if (!image) {
115  SDL_Surface* textSurface = renderString(text);
116  image = RenderBackend::instance()->createImage(textSurface);
117  m_pool.addRenderedText( this, text, image );
118  }
119  return image;
120  }
121 
122  Image* FontBase::getAsImageMultiline(const std::string& text) {
123  const uint8_t newline_utf8 = '\n';
124  uint32_t newline;
125  utf8::utf8to32(&newline_utf8,&newline_utf8 + 1,&newline);
126  //std::cout << "Text:" << text << std::endl;
127  Image* image = m_pool.getRenderedText(this, text);
128  if (!image) {
129  std::vector<SDL_Surface*> lines;
130  std::string::const_iterator it = text.begin();
131  // split text as needed
132  int32_t render_width = 0, render_height = 0;
133  do {
134  uint32_t codepoint = 0;
135  std::string line;
136  while( codepoint != newline && it != text.end() )
137  {
138  codepoint = utf8::next(it,text.end());
139  if( codepoint != newline )
140  utf8::append(codepoint, back_inserter(line));
141  }
142  //std::cout << "Line:" << line << std::endl;
143  SDL_Surface* text_surface = renderString(line);
144  if (text_surface->w > render_width) {
145  render_width = text_surface->w;
146  }
147  lines.push_back(text_surface);
148  } while (it != text.end());
149 
150  render_height = (getRowSpacing() + getHeight()) * lines.size();
151  SDL_Surface* final_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
152  render_width,render_height,32,
153  RMASK, GMASK, BMASK ,AMASK);
154  if (!final_surface) {
155  throw SDLException(std::string("CreateRGBSurface failed: ") + SDL_GetError());
156  }
157  SDL_FillRect(final_surface, 0, 0x00000000);
158  int32_t ypos = 0;
159  for (std::vector<SDL_Surface*>::iterator i = lines.begin(); i != lines.end(); ++i) {
160  SDL_Rect dst_rect = { 0, 0, 0, 0 };
161  dst_rect.y = ypos;
162 
163  SDL_SetAlpha(*i,0,SDL_ALPHA_OPAQUE);
164  SDL_BlitSurface(*i,0,final_surface,&dst_rect);
165  ypos += getRowSpacing() + getHeight();
166  SDL_FreeSurface(*i);
167  }
168  image = RenderBackend::instance()->createImage(final_surface);
169  m_pool.addRenderedText(this, text, image);
170  }
171  return image;
172  }
173 
174  std::string FontBase::splitTextToWidth (const std::string& text, int32_t render_width) {
175  const uint32_t whitespace = ' ';
176  const uint8_t newline_utf8 = '\n';
177  uint32_t newline;
178  utf8::utf8to32(&newline_utf8,&newline_utf8 + 1,&newline);
179  if (render_width <= 0 || text.empty()) {
180  return text;
181  }
182  std::string output;
183  std::string line;
184  std::string::const_iterator pos = text.begin();
185  std::list<std::pair<size_t,std::string::const_iterator> > break_pos;
186  bool firstLine = true;
187 
188  while( pos != text.end())
189  {
190  break_pos.clear();
191  if( !firstLine ) {
192  line = "\n";
193  } else {
194  firstLine = false;
195  }
196 
197  bool haveNewLine = false;
198  while( getWidth(line) < render_width && pos != text.end() )
199  {
200  uint32_t codepoint = utf8::next(pos, text.end());
201  if (codepoint == whitespace && !line.empty())
202  break_pos.push_back( std::make_pair(line.length(),pos) );
203 
204  if( codepoint != newline )
205  utf8::append(codepoint, back_inserter(line) );
206 
207  // Special case: Already newlines in string:
208  if( codepoint == newline ) {
209  output.append(line);
210  line = "";
211  haveNewLine = true;
212  break;
213  }
214  }
215  if( haveNewLine )
216  continue;
217 
218  if( pos == text.end() )
219  break;
220 
221  if( break_pos.empty() ) {
222  // No break position and line length smaller than 2
223  // means the renderwidth is really screwed. Just continue
224  // appending single character lines.
225  if( utf8::distance(line.begin(),line.end()) <= 1 && line != "\n") {
226  output.append(line);
227  continue;
228  }
229 
230  if (line == "\n") {
231  ++pos;
232  }
233 
234  // We can't do hyphenation here,
235  // so we just retreat one character :-(
236  // FIXME
237  //line = line.erase(line.length() - 1);
238  //--pos;
239  } else {
240  line = line.substr(0,break_pos.back().first);
241  pos = break_pos.back().second;
242  }
243  output.append(line);
244  }
245  if( !line.empty() ) {
246  output.append(line);
247  }
248  return output;
249  }
250 }
int32_t getGlyphSpacing() const
Definition: fontbase.cpp:68
Image * getAsImageMultiline(const std::string &text)
Definition: fontbase.cpp:122
void setAntiAlias(bool antiAlias)
Definition: fontbase.cpp:72
Image * getRenderedText(FontBase *fontbase, const std::string &text)
void setRowSpacing(int32_t spacing)
Definition: fontbase.cpp:56
void addRenderedText(FontBase *fontbase, const std::string &text, Image *image)
int32_t getRowSpacing() const
Definition: fontbase.cpp:60
virtual int32_t getHeight() const =0
Image * getAsImage(const std::string &text)
Definition: fontbase.cpp:112
void setGlyphSpacing(int32_t spacing)
Definition: fontbase.cpp:64
bool isAntiAlias()
Definition: fontbase.cpp:76
SDL_Color getColor() const
Definition: fontbase.cpp:80
virtual int32_t getWidth(const std::string &text) const =0