comparison ext/guichan-0.8.1/src/imagefont.cpp @ 89:fa33cda75471

* Reverting back to 2543 as requested by sleek
author mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222
date Sat, 19 Jul 2008 11:38:52 +0000
parents 4a0efb7baf70
children
comparison
equal deleted inserted replaced
88:1c2842ebe393 89:fa33cda75471
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 int w = mImage->getWidth();
102 int h = mImage->getHeight();
103 mImage->convertToDisplayFormat();
104
105 mRowSpacing = 0;
106 mGlyphSpacing = 0;
107 }
108
109 ImageFont::ImageFont(Image* image,
110 const std::string& glyphs)
111 {
112 mFilename = "Image*";
113 if (image == NULL)
114 {
115 GCN_EXCEPTION("Font image is NULL");
116 }
117 mImage = image;
118
119 Color separator = mImage->getPixel(0, 0);
120
121 int i = 0;
122 for (i = 0;
123 i < mImage->getWidth() && separator == mImage->getPixel(i, 0);
124 ++i)
125 {
126 }
127
128 if (i >= mImage->getWidth())
129 {
130 throw GCN_EXCEPTION("Corrupt image.");
131 }
132
133 int j = 0;
134 for (j = 0; j < mImage->getHeight(); ++j)
135 {
136 if (separator == mImage->getPixel(i, j))
137 {
138 break;
139 }
140 }
141
142 mHeight = j;
143 int x = 0, y = 0;
144 unsigned char k;
145
146 for (i = 0; i < (int)glyphs.size(); ++i)
147 {
148 k = glyphs.at(i);
149 mGlyph[k] = scanForGlyph(k, x, y, separator);
150 // Update x och y with new coordinates.
151 x = mGlyph[k].x + mGlyph[k].width;
152 y = mGlyph[k].y;
153 }
154
155 int w = mImage->getWidth();
156 int h = mImage->getHeight();
157 mImage->convertToDisplayFormat();
158
159 mRowSpacing = 0;
160 mGlyphSpacing = 0;
161 }
162
163 ImageFont::ImageFont(const std::string& filename,
164 unsigned char glyphsFrom,
165 unsigned char glyphsTo)
166 {
167 mFilename = filename;
168 mImage = Image::load(filename, false);
169
170 Color separator = mImage->getPixel(0, 0);
171
172 int i = 0;
173 for (i=0; separator == mImage->getPixel(i, 0)
174 && i < mImage->getWidth(); ++i)
175 {
176 }
177
178 if (i >= mImage->getWidth())
179 {
180 throw GCN_EXCEPTION("Corrupt image.");
181 }
182
183 int j = 0;
184 for (j = 0; j < mImage->getHeight(); ++j)
185 {
186 if (separator == mImage->getPixel(i, j))
187 {
188 break;
189 }
190 }
191
192 mHeight = j;
193 int x = 0, y = 0;
194
195 for (i = glyphsFrom; i < glyphsTo + 1; i++)
196 {
197 mGlyph[i] = scanForGlyph(i, x, y, separator);
198 // Update x och y with new coordinates.
199 x = mGlyph[i].x + mGlyph[i].width;
200 y = mGlyph[i].y;
201 }
202
203 int w = mImage->getWidth();
204 int h = mImage->getHeight();
205 mImage->convertToDisplayFormat();
206
207 mRowSpacing = 0;
208 mGlyphSpacing = 0;
209 }
210
211 ImageFont::~ImageFont()
212 {
213 delete mImage;
214 }
215
216 int ImageFont::getWidth(unsigned char glyph) const
217 {
218 if (mGlyph[glyph].width == 0)
219 {
220 return mGlyph[(int)(' ')].width + mGlyphSpacing;
221 }
222
223 return mGlyph[glyph].width + mGlyphSpacing;
224 }
225
226 int ImageFont::getHeight() const
227 {
228 return mHeight + mRowSpacing;
229 }
230
231 int ImageFont::drawGlyph(Graphics* graphics,
232 unsigned char glyph,
233 int x, int y)
234 {
235 // This is needed for drawing the glyph in the middle
236 // if we have spacing.
237 int yoffset = getRowSpacing() / 2;
238
239 if (mGlyph[glyph].width == 0)
240 {
241 graphics->drawRectangle(Rectangle(x,
242 y + 1 + yoffset,
243 mGlyph[(int)(' ')].width - 1,
244 mGlyph[(int)(' ')].height - 2));
245
246 return mGlyph[(int)(' ')].width + mGlyphSpacing;
247 }
248
249 graphics->drawImage(mImage,
250 mGlyph[glyph].x,
251 mGlyph[glyph].y,
252 x,
253 y + yoffset,
254 mGlyph[glyph].width,
255 mGlyph[glyph].height);
256
257 return mGlyph[glyph].width + mGlyphSpacing;
258 }
259
260 void ImageFont::drawString(Graphics* graphics,
261 const std::string& text,
262 int x,
263 int y)
264 {
265 unsigned int i;
266
267 for (i = 0; i < text.size(); ++i)
268 {
269 drawGlyph(graphics, text.at(i), x, y);
270 x += getWidth(text.at(i));
271 }
272 }
273
274 void ImageFont::setRowSpacing(int spacing)
275 {
276 mRowSpacing = spacing;
277 }
278
279 int ImageFont::getRowSpacing()
280 {
281 return mRowSpacing;
282 }
283
284 void ImageFont::setGlyphSpacing(int spacing)
285 {
286 mGlyphSpacing = spacing;
287 }
288
289 int ImageFont::getGlyphSpacing()
290 {
291 return mGlyphSpacing;
292 }
293
294 Rectangle ImageFont::scanForGlyph(unsigned char glyph,
295 int x,
296 int y,
297 const Color& separator)
298 {
299 Color color;
300 do
301 {
302 ++x;
303
304 if (x >= mImage->getWidth())
305 {
306 y += mHeight + 1;
307 x = 0;
308
309 if (y >= mImage->getHeight())
310 {
311 std::string str;
312 std::ostringstream os(str);
313 os << "Image ";
314 os << mFilename;
315 os << " with font is corrupt near character '";
316 os << glyph;
317 os << "'";
318 throw GCN_EXCEPTION(os.str());
319 }
320 }
321
322 color = mImage->getPixel(x, y);
323
324 } while (color == separator);
325
326 int width = 0;
327
328 do
329 {
330 ++width;
331
332 if (x + width >= mImage->getWidth())
333 {
334 std::string str;
335 std::ostringstream os(str);
336 os << "Image ";
337 os << mFilename;
338 os << " with font is corrupt near character '";
339 os << glyph;
340 os << "'";
341 throw GCN_EXCEPTION(os.str());
342 }
343
344 color = mImage->getPixel(x + width, y);
345
346 } while (color != separator);
347
348 return Rectangle(x, y, width, mHeight);
349 }
350
351 int ImageFont::getWidth(const std::string& text) const
352 {
353 unsigned int i;
354 int size = 0;
355
356 for (i = 0; i < text.size(); ++i)
357 {
358 size += getWidth(text.at(i));
359 }
360
361 return size - mGlyphSpacing;
362 }
363
364 int ImageFont::getStringIndexAt(const std::string& text, int x)
365 {
366 unsigned int i;
367 int size = 0;
368
369 for (i = 0; i < text.size(); ++i)
370 {
371 size += getWidth(text.at(i));
372
373 if (size > x)
374 {
375 return i;
376 }
377 }
378
379 return text.size();
380 }
381 }