comparison engine/core/video/fonts/fontbase.cpp @ 0:4a0efb7baf70

* Datasets becomes the new trunk and retires after that :-)
author mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222
date Sun, 29 Jun 2008 18:44:17 +0000
parents
children 90005975cdbb
comparison
equal deleted inserted replaced
-1:000000000000 0:4a0efb7baf70
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 modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program 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 *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin St, 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 #include <boost/filesystem/convenience.hpp>
29
30 // FIFE includes
31 // These includes are split up in two parts, separated by one empty line
32 // First block: files included from the FIFE root src directory
33 // Second block: files included from the same folder
34 #include "util/structures/rect.h"
35 #include "util/base/exception.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::setRowSpacing(int spacing) {
53 mRowSpacing = spacing;
54 }
55
56 int FontBase::getRowSpacing() const {
57 return mRowSpacing;
58 }
59
60 void FontBase::setGlyphSpacing(int spacing) {
61 mGlyphSpacing = spacing;
62 }
63
64 int FontBase::getGlyphSpacing() const {
65 return mGlyphSpacing;
66 }
67
68 void FontBase::setAntiAlias(bool antiAlias) {
69 m_antiAlias = antiAlias;
70 }
71
72 bool FontBase::isAntiAlias() {
73 return m_antiAlias;
74 }
75
76 SDL_Color FontBase::getColor() const {
77 return mColor;
78 }
79
80 int FontBase::getStringIndexAt(const std::string &text, int x) {
81 for (int i = 0; i < static_cast<int>(text.size()); ++i) {
82 if (getWidth(text.substr(0,i)) > x) {
83 return i-1;
84 }
85 }
86 return text.length();
87 }
88
89 Image* FontBase::getAsImage(const std::string& text) {
90 Image* image = m_pool.getRenderedText(this, text);
91 if (!image) {
92 SDL_Surface* textSurface = renderString(text);
93 image = RenderBackend::instance()->createImage(textSurface);
94 m_pool.addRenderedText( this, text, image );
95 }
96 return image;
97 }
98
99 Image* FontBase::getAsImageMultiline(const std::string& text) {
100 Image* image = m_pool.getRenderedText(this, text);
101 if (!image) {
102 std::vector<SDL_Surface*> lines;
103
104 // split text as needed
105 std::string::size_type pos, last_pos = 0;
106 int length = 0;
107 int render_width = 0, render_height = 0;
108 do {
109 pos = text.find("\n", last_pos);
110 if (pos != std::string::npos) {
111 length = pos - last_pos;
112 } else {
113 length = text.size() - last_pos;
114 }
115 std::string sub = text.substr(last_pos, length);
116 SDL_Surface* text_surface = renderString(sub);
117 if (text_surface->w > render_width) {
118 render_width = text_surface->w;
119 }
120 lines.push_back(text_surface);
121 last_pos = pos + 1;
122 } while (pos != std::string::npos);
123 render_height = (getRowSpacing() + getHeight()) * lines.size();
124 SDL_Surface* final_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
125 render_width,render_height,32,
126 RMASK, GMASK, BMASK ,AMASK);
127 if (!final_surface) {
128 std::cerr << "CreateRGBSurface failed: " << SDL_GetError() << "\n";
129 exit(0);
130 }
131 SDL_FillRect(final_surface, 0, 0x00000000);
132 int ypos = 0;
133 for (std::vector<SDL_Surface*>::iterator i = lines.begin(); i != lines.end(); ++i) {
134 SDL_Rect dst_rect = { 0, 0, 0, 0 };
135 dst_rect.y = ypos;
136
137 SDL_SetAlpha(*i,0,SDL_ALPHA_OPAQUE);
138 SDL_BlitSurface(*i,0,final_surface,&dst_rect);
139 ypos += getRowSpacing() + getHeight();
140 SDL_FreeSurface(*i);
141 }
142 image = RenderBackend::instance()->createImage(final_surface);
143 m_pool.addRenderedText(this, text, image);
144 }
145 return image;
146 }
147
148 std::string FontBase::splitTextToWidth (const std::string& text, int render_width) {
149 if (render_width <= 0 || text.empty()) {
150 return text;
151 }
152 std::string output;
153 std::string line;
154 std::string::size_type pos = 0;
155 std::list<std::pair<size_t,size_t> > break_pos;
156 bool firstLine = true;
157
158 while( pos < text.length() )
159 {
160 break_pos.clear();
161 if( !firstLine ) {
162 line = "\n";
163 } else {
164 firstLine = false;
165 }
166
167 while( getWidth(line) < render_width && pos < text.length() )
168 {
169 if (text.at(pos) == ' ' && !line.empty())
170 break_pos.push_back( std::make_pair(line.length(),pos) );
171 line.push_back( text.at(pos) );
172 ++pos;
173
174 // Special case: Already newlines in string:
175 if( text.at(pos-1) == '\n' ) {
176 if( line[0] == '\n' && line.length() > 1 )
177 line.erase(0);
178 output.append(line);
179 break;
180 }
181 }
182 if( pos >= text.length() )
183 break;
184
185 if( break_pos.empty() ) {
186 // No break position and line length smaller than 2
187 // means the renderwidth is really screwed. Just continue
188 // appending single character lines.
189 if( line.length() <= 1 ) {
190 output.append(line);
191 continue;
192 }
193
194 // We can't do hyphenation here,
195 // so we just retreat one character :-(
196 line.erase(line.length() - 1);
197 --pos;
198 } else {
199 line = line.substr(0,break_pos.back().first);
200 pos = break_pos.back().second + 1;
201 }
202 output.append(line);
203 }
204 if( !line.empty() ) {
205 output.append(line);
206 }
207 return output;
208 }
209 }