comparison ext/guichan-0.8.2/src/imagefont.cpp @ 378:64738befdf3b

bringing in the changes from the build_system_rework branch in preparation for the 0.3.0 release. This commit will require the Jan2010 devkit. Clients will also need to be modified to the new way to import fife.
author vtchill@33b003aa-7bff-0310-803a-e67f0ece8222
date Mon, 11 Jan 2010 23:34:52 +0000
parents
children
comparison
equal deleted inserted replaced
377:fe6fb0e0ed23 378:64738befdf3b
1 /* _______ __ __ __ ______ __ __ _______ __ __
2 * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
3 * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
4 * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
5 * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
6 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
7 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
8 *
9 * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
10 *
11 *
12 * Per Larsson a.k.a finalman
13 * Olof Naessén a.k.a jansem/yakslem
14 *
15 * Visit: http://guichan.sourceforge.net
16 *
17 * License: (BSD)
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in
25 * the documentation and/or other materials provided with the
26 * distribution.
27 * 3. Neither the name of Guichan nor the names of its contributors may
28 * be used to endorse or promote products derived from this software
29 * without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
37 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
38 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
39 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
40 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 */
43
44 /*
45 * For comments regarding functions please see the header file.
46 */
47
48 #include "guichan/imagefont.hpp"
49
50 #include <sstream>
51
52 #include "guichan/color.hpp"
53 #include "guichan/exception.hpp"
54 #include "guichan/graphics.hpp"
55 #include "guichan/image.hpp"
56
57 namespace gcn
58 {
59 ImageFont::ImageFont(const std::string& filename,
60 const std::string& glyphs)
61 {
62 mFilename = filename;
63 mImage = Image::load(filename, false);
64
65 Color separator = mImage->getPixel(0, 0);
66
67 int i = 0;
68 for (i = 0;
69 i < mImage->getWidth() && separator == mImage->getPixel(i, 0);
70 ++i)
71 {
72 }
73
74 if (i >= mImage->getWidth())
75 {
76 throw GCN_EXCEPTION("Corrupt image.");
77 }
78
79 int j = 0;
80 for (j = 0; j < mImage->getHeight(); ++j)
81 {
82 if (separator == mImage->getPixel(i, j))
83 {
84 break;
85 }
86 }
87
88 mHeight = j;
89 int x = 0, y = 0;
90 unsigned char k;
91
92 for (i = 0; i < (int)glyphs.size(); ++i)
93 {
94 k = glyphs.at(i);
95 mGlyph[k] = scanForGlyph(k, x, y, separator);
96 // Update x och y with new coordinates.
97 x = mGlyph[k].x + mGlyph[k].width;
98 y = mGlyph[k].y;
99 }
100
101 mImage->convertToDisplayFormat();
102
103 mRowSpacing = 0;
104 mGlyphSpacing = 0;
105 }
106
107 ImageFont::ImageFont(Image* image,
108 const std::string& glyphs)
109 {
110 mFilename = "Image*";
111 if (image == NULL)
112 {
113 GCN_EXCEPTION("Font image is NULL");
114 }
115 mImage = image;
116
117 Color separator = mImage->getPixel(0, 0);
118
119 int i = 0;
120 for (i = 0;
121 i < mImage->getWidth() && separator == mImage->getPixel(i, 0);
122 ++i)
123 {
124 }
125
126 if (i >= mImage->getWidth())
127 {
128 throw GCN_EXCEPTION("Corrupt image.");
129 }
130
131 int j = 0;
132 for (j = 0; j < mImage->getHeight(); ++j)
133 {
134 if (separator == mImage->getPixel(i, j))
135 {
136 break;
137 }
138 }
139
140 mHeight = j;
141 int x = 0, y = 0;
142 unsigned char k;
143
144 for (i = 0; i < (int)glyphs.size(); ++i)
145 {
146 k = glyphs.at(i);
147 mGlyph[k] = scanForGlyph(k, x, y, separator);
148 // Update x och y with new coordinates.
149 x = mGlyph[k].x + mGlyph[k].width;
150 y = mGlyph[k].y;
151 }
152
153 mImage->convertToDisplayFormat();
154
155 mRowSpacing = 0;
156 mGlyphSpacing = 0;
157 }
158
159 ImageFont::ImageFont(const std::string& filename,
160 unsigned char glyphsFrom,
161 unsigned char glyphsTo)
162 {
163 mFilename = filename;
164 mImage = Image::load(filename, false);
165
166 Color separator = mImage->getPixel(0, 0);
167
168 int i = 0;
169 for (i=0; separator == mImage->getPixel(i, 0)
170 && i < mImage->getWidth(); ++i)
171 {
172 }
173
174 if (i >= mImage->getWidth())
175 {
176 throw GCN_EXCEPTION("Corrupt image.");
177 }
178
179 int j = 0;
180 for (j = 0; j < mImage->getHeight(); ++j)
181 {
182 if (separator == mImage->getPixel(i, j))
183 {
184 break;
185 }
186 }
187
188 mHeight = j;
189 int x = 0, y = 0;
190
191 for (i = glyphsFrom; i < glyphsTo + 1; i++)
192 {
193 mGlyph[i] = scanForGlyph(i, x, y, separator);
194 // Update x och y with new coordinates.
195 x = mGlyph[i].x + mGlyph[i].width;
196 y = mGlyph[i].y;
197 }
198
199 mImage->convertToDisplayFormat();
200
201 mRowSpacing = 0;
202 mGlyphSpacing = 0;
203 }
204
205 ImageFont::~ImageFont()
206 {
207 delete mImage;
208 }
209
210 int ImageFont::getWidth(unsigned char glyph) const
211 {
212 if (mGlyph[glyph].width == 0)
213 {
214 return mGlyph[(int)(' ')].width + mGlyphSpacing;
215 }
216
217 return mGlyph[glyph].width + mGlyphSpacing;
218 }
219
220 int ImageFont::getHeight() const
221 {
222 return mHeight + mRowSpacing;
223 }
224
225 int ImageFont::drawGlyph(Graphics* graphics,
226 unsigned char glyph,
227 int x, int y)
228 {
229 // This is needed for drawing the glyph in the middle
230 // if we have spacing.
231 int yoffset = getRowSpacing() / 2;
232
233 if (mGlyph[glyph].width == 0)
234 {
235 graphics->drawRectangle(Rectangle(x,
236 y + 1 + yoffset,
237 mGlyph[(int)(' ')].width - 1,
238 mGlyph[(int)(' ')].height - 2));
239
240 return mGlyph[(int)(' ')].width + mGlyphSpacing;
241 }
242
243 graphics->drawImage(mImage,
244 mGlyph[glyph].x,
245 mGlyph[glyph].y,
246 x,
247 y + yoffset,
248 mGlyph[glyph].width,
249 mGlyph[glyph].height);
250
251 return mGlyph[glyph].width + mGlyphSpacing;
252 }
253
254 void ImageFont::drawString(Graphics* graphics,
255 const std::string& text,
256 int x,
257 int y)
258 {
259 unsigned int i;
260
261 for (i = 0; i < text.size(); ++i)
262 {
263 drawGlyph(graphics, text.at(i), x, y);
264 x += getWidth(text.at(i));
265 }
266 }
267
268 void ImageFont::setRowSpacing(int spacing)
269 {
270 mRowSpacing = spacing;
271 }
272
273 int ImageFont::getRowSpacing()
274 {
275 return mRowSpacing;
276 }
277
278 void ImageFont::setGlyphSpacing(int spacing)
279 {
280 mGlyphSpacing = spacing;
281 }
282
283 int ImageFont::getGlyphSpacing()
284 {
285 return mGlyphSpacing;
286 }
287
288 Rectangle ImageFont::scanForGlyph(unsigned char glyph,
289 int x,
290 int y,
291 const Color& separator)
292 {
293 Color color;
294 do
295 {
296 ++x;
297
298 if (x >= mImage->getWidth())
299 {
300 y += mHeight + 1;
301 x = 0;
302
303 if (y >= mImage->getHeight())
304 {
305 std::string str;
306 std::ostringstream os(str);
307 os << "Image ";
308 os << mFilename;
309 os << " with font is corrupt near character '";
310 os << glyph;
311 os << "'";
312 throw GCN_EXCEPTION(os.str());
313 }
314 }
315
316 color = mImage->getPixel(x, y);
317
318 } while (color == separator);
319
320 int width = 0;
321
322 do
323 {
324 ++width;
325
326 if (x + width >= mImage->getWidth())
327 {
328 std::string str;
329 std::ostringstream os(str);
330 os << "Image ";
331 os << mFilename;
332 os << " with font is corrupt near character '";
333 os << glyph;
334 os << "'";
335 throw GCN_EXCEPTION(os.str());
336 }
337
338 color = mImage->getPixel(x + width, y);
339
340 } while (color != separator);
341
342 return Rectangle(x, y, width, mHeight);
343 }
344
345 int ImageFont::getWidth(const std::string& text) const
346 {
347 unsigned int i;
348 int size = 0;
349
350 for (i = 0; i < text.size(); ++i)
351 {
352 size += getWidth(text.at(i));
353 }
354
355 return size - mGlyphSpacing;
356 }
357
358 int ImageFont::getStringIndexAt(const std::string& text, int x) const
359 {
360 unsigned int i;
361 int size = 0;
362
363 for (i = 0; i < text.size(); ++i)
364 {
365 size += getWidth(text.at(i));
366
367 if (size > x)
368 {
369 return i;
370 }
371 }
372
373 return text.size();
374 }
375 }