aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/CGUIFont.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CGUIFont.cpp')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/CGUIFont.cpp1178
1 files changed, 589 insertions, 589 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CGUIFont.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CGUIFont.cpp
index 8c7f85f..b2db857 100644
--- a/libraries/irrlicht-1.8/source/Irrlicht/CGUIFont.cpp
+++ b/libraries/irrlicht-1.8/source/Irrlicht/CGUIFont.cpp
@@ -1,589 +1,589 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt 1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine". 2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h 3// For conditions of distribution and use, see copyright notice in irrlicht.h
4 4
5#include "CGUIFont.h" 5#include "CGUIFont.h"
6#ifdef _IRR_COMPILE_WITH_GUI_ 6#ifdef _IRR_COMPILE_WITH_GUI_
7 7
8#include "os.h" 8#include "os.h"
9#include "IGUIEnvironment.h" 9#include "IGUIEnvironment.h"
10#include "IXMLReader.h" 10#include "IXMLReader.h"
11#include "IReadFile.h" 11#include "IReadFile.h"
12#include "IVideoDriver.h" 12#include "IVideoDriver.h"
13#include "IGUISpriteBank.h" 13#include "IGUISpriteBank.h"
14 14
15namespace irr 15namespace irr
16{ 16{
17namespace gui 17namespace gui
18{ 18{
19 19
20//! constructor 20//! constructor
21CGUIFont::CGUIFont(IGUIEnvironment *env, const io::path& filename) 21CGUIFont::CGUIFont(IGUIEnvironment *env, const io::path& filename)
22: Driver(0), SpriteBank(0), Environment(env), WrongCharacter(0), 22: Driver(0), SpriteBank(0), Environment(env), WrongCharacter(0),
23 MaxHeight(0), GlobalKerningWidth(0), GlobalKerningHeight(0) 23 MaxHeight(0), GlobalKerningWidth(0), GlobalKerningHeight(0)
24{ 24{
25 #ifdef _DEBUG 25 #ifdef _DEBUG
26 setDebugName("CGUIFont"); 26 setDebugName("CGUIFont");
27 #endif 27 #endif
28 28
29 if (Environment) 29 if (Environment)
30 { 30 {
31 // don't grab environment, to avoid circular references 31 // don't grab environment, to avoid circular references
32 Driver = Environment->getVideoDriver(); 32 Driver = Environment->getVideoDriver();
33 33
34 SpriteBank = Environment->getSpriteBank(filename); 34 SpriteBank = Environment->getSpriteBank(filename);
35 if (!SpriteBank) // could be default-font which has no file 35 if (!SpriteBank) // could be default-font which has no file
36 SpriteBank = Environment->addEmptySpriteBank(filename); 36 SpriteBank = Environment->addEmptySpriteBank(filename);
37 if (SpriteBank) 37 if (SpriteBank)
38 SpriteBank->grab(); 38 SpriteBank->grab();
39 } 39 }
40 40
41 if (Driver) 41 if (Driver)
42 Driver->grab(); 42 Driver->grab();
43 43
44 setInvisibleCharacters ( L" " ); 44 setInvisibleCharacters ( L" " );
45} 45}
46 46
47 47
48//! destructor 48//! destructor
49CGUIFont::~CGUIFont() 49CGUIFont::~CGUIFont()
50{ 50{
51 if (Driver) 51 if (Driver)
52 Driver->drop(); 52 Driver->drop();
53 53
54 if (SpriteBank) 54 if (SpriteBank)
55 { 55 {
56 SpriteBank->drop(); 56 SpriteBank->drop();
57 // TODO: spritebank still exists in gui-environment and should be removed here when it's 57 // TODO: spritebank still exists in gui-environment and should be removed here when it's
58 // reference-count is 1. Just can't do that from here at the moment. 58 // reference-count is 1. Just can't do that from here at the moment.
59 // But spritebank would not be able to drop textures anyway because those are in texture-cache 59 // But spritebank would not be able to drop textures anyway because those are in texture-cache
60 // where they can't be removed unless materials start reference-couting 'em. 60 // where they can't be removed unless materials start reference-couting 'em.
61 } 61 }
62} 62}
63 63
64 64
65//! loads a font file from xml 65//! loads a font file from xml
66bool CGUIFont::load(io::IXMLReader* xml) 66bool CGUIFont::load(io::IXMLReader* xml)
67{ 67{
68 if (!SpriteBank) 68 if (!SpriteBank)
69 return false; 69 return false;
70 70
71 SpriteBank->clear(); 71 SpriteBank->clear();
72 72
73 while (xml->read()) 73 while (xml->read())
74 { 74 {
75 if (io::EXN_ELEMENT == xml->getNodeType()) 75 if (io::EXN_ELEMENT == xml->getNodeType())
76 { 76 {
77 if (core::stringw(L"Texture") == xml->getNodeName()) 77 if (core::stringw(L"Texture") == xml->getNodeName())
78 { 78 {
79 // add a texture 79 // add a texture
80 core::stringc fn = xml->getAttributeValue(L"filename"); 80 core::stringc fn = xml->getAttributeValue(L"filename");
81 u32 i = (u32)xml->getAttributeValueAsInt(L"index"); 81 u32 i = (u32)xml->getAttributeValueAsInt(L"index");
82 core::stringw alpha = xml->getAttributeValue(L"hasAlpha"); 82 core::stringw alpha = xml->getAttributeValue(L"hasAlpha");
83 83
84 while (i+1 > SpriteBank->getTextureCount()) 84 while (i+1 > SpriteBank->getTextureCount())
85 SpriteBank->addTexture(0); 85 SpriteBank->addTexture(0);
86 86
87 // disable mipmaps+filtering 87 // disable mipmaps+filtering
88 bool mipmap = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); 88 bool mipmap = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
89 Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); 89 Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
90 90
91 // load texture 91 // load texture
92 SpriteBank->setTexture(i, Driver->getTexture(fn)); 92 SpriteBank->setTexture(i, Driver->getTexture(fn));
93 93
94 // set previous mip-map+filter state 94 // set previous mip-map+filter state
95 Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap); 95 Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap);
96 96
97 // couldn't load texture, abort. 97 // couldn't load texture, abort.
98 if (!SpriteBank->getTexture(i)) 98 if (!SpriteBank->getTexture(i))
99 { 99 {
100 os::Printer::log("Unable to load all textures in the font, aborting", ELL_ERROR); 100 os::Printer::log("Unable to load all textures in the font, aborting", ELL_ERROR);
101 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; 101 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
102 return false; 102 return false;
103 } 103 }
104 else 104 else
105 { 105 {
106 // colorkey texture rather than alpha channel? 106 // colorkey texture rather than alpha channel?
107 if (alpha == core::stringw("false")) 107 if (alpha == core::stringw("false"))
108 Driver->makeColorKeyTexture(SpriteBank->getTexture(i), core::position2di(0,0)); 108 Driver->makeColorKeyTexture(SpriteBank->getTexture(i), core::position2di(0,0));
109 } 109 }
110 } 110 }
111 else if (core::stringw(L"c") == xml->getNodeName()) 111 else if (core::stringw(L"c") == xml->getNodeName())
112 { 112 {
113 // adding a character to this font 113 // adding a character to this font
114 SFontArea a; 114 SFontArea a;
115 SGUISpriteFrame f; 115 SGUISpriteFrame f;
116 SGUISprite s; 116 SGUISprite s;
117 core::rect<s32> rectangle; 117 core::rect<s32> rectangle;
118 118
119 a.underhang = xml->getAttributeValueAsInt(L"u"); 119 a.underhang = xml->getAttributeValueAsInt(L"u");
120 a.overhang = xml->getAttributeValueAsInt(L"o"); 120 a.overhang = xml->getAttributeValueAsInt(L"o");
121 a.spriteno = SpriteBank->getSprites().size(); 121 a.spriteno = SpriteBank->getSprites().size();
122 s32 texno = xml->getAttributeValueAsInt(L"i"); 122 s32 texno = xml->getAttributeValueAsInt(L"i");
123 123
124 // parse rectangle 124 // parse rectangle
125 core::stringc rectstr = xml->getAttributeValue(L"r"); 125 core::stringc rectstr = xml->getAttributeValue(L"r");
126 wchar_t ch = xml->getAttributeValue(L"c")[0]; 126 wchar_t ch = xml->getAttributeValue(L"c")[0];
127 127
128 const c8 *c = rectstr.c_str(); 128 const c8 *c = rectstr.c_str();
129 s32 val; 129 s32 val;
130 val = 0; 130 val = 0;
131 while (*c >= '0' && *c <= '9') 131 while (*c >= '0' && *c <= '9')
132 { 132 {
133 val *= 10; 133 val *= 10;
134 val += *c - '0'; 134 val += *c - '0';
135 c++; 135 c++;
136 } 136 }
137 rectangle.UpperLeftCorner.X = val; 137 rectangle.UpperLeftCorner.X = val;
138 while (*c == L' ' || *c == L',') c++; 138 while (*c == L' ' || *c == L',') c++;
139 139
140 val = 0; 140 val = 0;
141 while (*c >= '0' && *c <= '9') 141 while (*c >= '0' && *c <= '9')
142 { 142 {
143 val *= 10; 143 val *= 10;
144 val += *c - '0'; 144 val += *c - '0';
145 c++; 145 c++;
146 } 146 }
147 rectangle.UpperLeftCorner.Y = val; 147 rectangle.UpperLeftCorner.Y = val;
148 while (*c == L' ' || *c == L',') c++; 148 while (*c == L' ' || *c == L',') c++;
149 149
150 val = 0; 150 val = 0;
151 while (*c >= '0' && *c <= '9') 151 while (*c >= '0' && *c <= '9')
152 { 152 {
153 val *= 10; 153 val *= 10;
154 val += *c - '0'; 154 val += *c - '0';
155 c++; 155 c++;
156 } 156 }
157 rectangle.LowerRightCorner.X = val; 157 rectangle.LowerRightCorner.X = val;
158 while (*c == L' ' || *c == L',') c++; 158 while (*c == L' ' || *c == L',') c++;
159 159
160 val = 0; 160 val = 0;
161 while (*c >= '0' && *c <= '9') 161 while (*c >= '0' && *c <= '9')
162 { 162 {
163 val *= 10; 163 val *= 10;
164 val += *c - '0'; 164 val += *c - '0';
165 c++; 165 c++;
166 } 166 }
167 rectangle.LowerRightCorner.Y = val; 167 rectangle.LowerRightCorner.Y = val;
168 168
169 CharacterMap.insert(ch,Areas.size()); 169 CharacterMap.insert(ch,Areas.size());
170 170
171 // make frame 171 // make frame
172 f.rectNumber = SpriteBank->getPositions().size(); 172 f.rectNumber = SpriteBank->getPositions().size();
173 f.textureNumber = texno; 173 f.textureNumber = texno;
174 174
175 // add frame to sprite 175 // add frame to sprite
176 s.Frames.push_back(f); 176 s.Frames.push_back(f);
177 s.frameTime = 0; 177 s.frameTime = 0;
178 178
179 // add rectangle to sprite bank 179 // add rectangle to sprite bank
180 SpriteBank->getPositions().push_back(rectangle); 180 SpriteBank->getPositions().push_back(rectangle);
181 a.width = rectangle.getWidth(); 181 a.width = rectangle.getWidth();
182 182
183 // add sprite to sprite bank 183 // add sprite to sprite bank
184 SpriteBank->getSprites().push_back(s); 184 SpriteBank->getSprites().push_back(s);
185 185
186 // add character to font 186 // add character to font
187 Areas.push_back(a); 187 Areas.push_back(a);
188 } 188 }
189 } 189 }
190 } 190 }
191 191
192 // set bad character 192 // set bad character
193 WrongCharacter = getAreaFromCharacter(L' '); 193 WrongCharacter = getAreaFromCharacter(L' ');
194 194
195 setMaxHeight(); 195 setMaxHeight();
196 196
197 return true; 197 return true;
198} 198}
199 199
200 200
201void CGUIFont::setMaxHeight() 201void CGUIFont::setMaxHeight()
202{ 202{
203 if ( !SpriteBank ) 203 if ( !SpriteBank )
204 return; 204 return;
205 205
206 MaxHeight = 0; 206 MaxHeight = 0;
207 s32 t; 207 s32 t;
208 208
209 core::array< core::rect<s32> >& p = SpriteBank->getPositions(); 209 core::array< core::rect<s32> >& p = SpriteBank->getPositions();
210 210
211 for (u32 i=0; i<p.size(); ++i) 211 for (u32 i=0; i<p.size(); ++i)
212 { 212 {
213 t = p[i].getHeight(); 213 t = p[i].getHeight();
214 if (t>MaxHeight) 214 if (t>MaxHeight)
215 MaxHeight = t; 215 MaxHeight = t;
216 } 216 }
217 217
218} 218}
219 219
220 220
221//! loads a font file, native file needed, for texture parsing 221//! loads a font file, native file needed, for texture parsing
222bool CGUIFont::load(io::IReadFile* file) 222bool CGUIFont::load(io::IReadFile* file)
223{ 223{
224 if (!Driver) 224 if (!Driver)
225 return false; 225 return false;
226 226
227 return loadTexture(Driver->createImageFromFile(file), 227 return loadTexture(Driver->createImageFromFile(file),
228 file->getFileName()); 228 file->getFileName());
229} 229}
230 230
231 231
232//! loads a font file, native file needed, for texture parsing 232//! loads a font file, native file needed, for texture parsing
233bool CGUIFont::load(const io::path& filename) 233bool CGUIFont::load(const io::path& filename)
234{ 234{
235 if (!Driver) 235 if (!Driver)
236 return false; 236 return false;
237 237
238 return loadTexture(Driver->createImageFromFile( filename ), 238 return loadTexture(Driver->createImageFromFile( filename ),
239 filename); 239 filename);
240} 240}
241 241
242 242
243//! load & prepare font from ITexture 243//! load & prepare font from ITexture
244bool CGUIFont::loadTexture(video::IImage* image, const io::path& name) 244bool CGUIFont::loadTexture(video::IImage* image, const io::path& name)
245{ 245{
246 if (!image || !SpriteBank) 246 if (!image || !SpriteBank)
247 return false; 247 return false;
248 248
249 s32 lowerRightPositions = 0; 249 s32 lowerRightPositions = 0;
250 250
251 video::IImage* tmpImage=image; 251 video::IImage* tmpImage=image;
252 bool deleteTmpImage=false; 252 bool deleteTmpImage=false;
253 switch(image->getColorFormat()) 253 switch(image->getColorFormat())
254 { 254 {
255 case video::ECF_R5G6B5: 255 case video::ECF_R5G6B5:
256 tmpImage = Driver->createImage(video::ECF_A1R5G5B5,image->getDimension()); 256 tmpImage = Driver->createImage(video::ECF_A1R5G5B5,image->getDimension());
257 image->copyTo(tmpImage); 257 image->copyTo(tmpImage);
258 deleteTmpImage=true; 258 deleteTmpImage=true;
259 break; 259 break;
260 case video::ECF_A1R5G5B5: 260 case video::ECF_A1R5G5B5:
261 case video::ECF_A8R8G8B8: 261 case video::ECF_A8R8G8B8:
262 break; 262 break;
263 case video::ECF_R8G8B8: 263 case video::ECF_R8G8B8:
264 tmpImage = Driver->createImage(video::ECF_A8R8G8B8,image->getDimension()); 264 tmpImage = Driver->createImage(video::ECF_A8R8G8B8,image->getDimension());
265 image->copyTo(tmpImage); 265 image->copyTo(tmpImage);
266 deleteTmpImage=true; 266 deleteTmpImage=true;
267 break; 267 break;
268 default: 268 default:
269 os::Printer::log("Unknown texture format provided for CGUIFont::loadTexture", ELL_ERROR); 269 os::Printer::log("Unknown texture format provided for CGUIFont::loadTexture", ELL_ERROR);
270 return false; 270 return false;
271 } 271 }
272 readPositions(tmpImage, lowerRightPositions); 272 readPositions(tmpImage, lowerRightPositions);
273 273
274 WrongCharacter = getAreaFromCharacter(L' '); 274 WrongCharacter = getAreaFromCharacter(L' ');
275 275
276 // output warnings 276 // output warnings
277 if (!lowerRightPositions || !SpriteBank->getSprites().size()) 277 if (!lowerRightPositions || !SpriteBank->getSprites().size())
278 os::Printer::log("Either no upper or lower corner pixels in the font file. If this font was made using the new font tool, please load the XML file instead. If not, the font may be corrupted.", ELL_ERROR); 278 os::Printer::log("Either no upper or lower corner pixels in the font file. If this font was made using the new font tool, please load the XML file instead. If not, the font may be corrupted.", ELL_ERROR);
279 else 279 else
280 if (lowerRightPositions != (s32)SpriteBank->getPositions().size()) 280 if (lowerRightPositions != (s32)SpriteBank->getPositions().size())
281 os::Printer::log("The amount of upper corner pixels and the lower corner pixels is not equal, font file may be corrupted.", ELL_ERROR); 281 os::Printer::log("The amount of upper corner pixels and the lower corner pixels is not equal, font file may be corrupted.", ELL_ERROR);
282 282
283 bool ret = ( !SpriteBank->getSprites().empty() && lowerRightPositions ); 283 bool ret = ( !SpriteBank->getSprites().empty() && lowerRightPositions );
284 284
285 if ( ret ) 285 if ( ret )
286 { 286 {
287 bool flag[2]; 287 bool flag[2];
288 flag[0] = Driver->getTextureCreationFlag ( video::ETCF_ALLOW_NON_POWER_2 ); 288 flag[0] = Driver->getTextureCreationFlag ( video::ETCF_ALLOW_NON_POWER_2 );
289 flag[1] = Driver->getTextureCreationFlag ( video::ETCF_CREATE_MIP_MAPS ); 289 flag[1] = Driver->getTextureCreationFlag ( video::ETCF_CREATE_MIP_MAPS );
290 290
291 Driver->setTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2, true); 291 Driver->setTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2, true);
292 Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false ); 292 Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false );
293 293
294 SpriteBank->addTexture(Driver->addTexture(name, tmpImage)); 294 SpriteBank->addTexture(Driver->addTexture(name, tmpImage));
295 295
296 Driver->setTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2, flag[0] ); 296 Driver->setTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2, flag[0] );
297 Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, flag[1] ); 297 Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, flag[1] );
298 } 298 }
299 if (deleteTmpImage) 299 if (deleteTmpImage)
300 tmpImage->drop(); 300 tmpImage->drop();
301 image->drop(); 301 image->drop();
302 302
303 setMaxHeight(); 303 setMaxHeight();
304 304
305 return ret; 305 return ret;
306} 306}
307 307
308 308
309void CGUIFont::readPositions(video::IImage* image, s32& lowerRightPositions) 309void CGUIFont::readPositions(video::IImage* image, s32& lowerRightPositions)
310{ 310{
311 if (!SpriteBank ) 311 if (!SpriteBank )
312 return; 312 return;
313 313
314 const core::dimension2d<u32> size = image->getDimension(); 314 const core::dimension2d<u32> size = image->getDimension();
315 315
316 video::SColor colorTopLeft = image->getPixel(0,0); 316 video::SColor colorTopLeft = image->getPixel(0,0);
317 colorTopLeft.setAlpha(255); 317 colorTopLeft.setAlpha(255);
318 image->setPixel(0,0,colorTopLeft); 318 image->setPixel(0,0,colorTopLeft);
319 video::SColor colorLowerRight = image->getPixel(1,0); 319 video::SColor colorLowerRight = image->getPixel(1,0);
320 video::SColor colorBackGround = image->getPixel(2,0); 320 video::SColor colorBackGround = image->getPixel(2,0);
321 video::SColor colorBackGroundTransparent = 0; 321 video::SColor colorBackGroundTransparent = 0;
322 322
323 image->setPixel(1,0,colorBackGround); 323 image->setPixel(1,0,colorBackGround);
324 324
325 // start parsing 325 // start parsing
326 326
327 core::position2d<s32> pos(0,0); 327 core::position2d<s32> pos(0,0);
328 for (pos.Y=0; pos.Y<(s32)size.Height; ++pos.Y) 328 for (pos.Y=0; pos.Y<(s32)size.Height; ++pos.Y)
329 { 329 {
330 for (pos.X=0; pos.X<(s32)size.Width; ++pos.X) 330 for (pos.X=0; pos.X<(s32)size.Width; ++pos.X)
331 { 331 {
332 const video::SColor c = image->getPixel(pos.X, pos.Y); 332 const video::SColor c = image->getPixel(pos.X, pos.Y);
333 if (c == colorTopLeft) 333 if (c == colorTopLeft)
334 { 334 {
335 image->setPixel(pos.X, pos.Y, colorBackGroundTransparent); 335 image->setPixel(pos.X, pos.Y, colorBackGroundTransparent);
336 SpriteBank->getPositions().push_back(core::rect<s32>(pos, pos)); 336 SpriteBank->getPositions().push_back(core::rect<s32>(pos, pos));
337 } 337 }
338 else 338 else
339 if (c == colorLowerRight) 339 if (c == colorLowerRight)
340 { 340 {
341 // too many lower right points 341 // too many lower right points
342 if (SpriteBank->getPositions().size()<=(u32)lowerRightPositions) 342 if (SpriteBank->getPositions().size()<=(u32)lowerRightPositions)
343 { 343 {
344 lowerRightPositions = 0; 344 lowerRightPositions = 0;
345 return; 345 return;
346 } 346 }
347 347
348 image->setPixel(pos.X, pos.Y, colorBackGroundTransparent); 348 image->setPixel(pos.X, pos.Y, colorBackGroundTransparent);
349 SpriteBank->getPositions()[lowerRightPositions].LowerRightCorner = pos; 349 SpriteBank->getPositions()[lowerRightPositions].LowerRightCorner = pos;
350 // add frame to sprite bank 350 // add frame to sprite bank
351 SGUISpriteFrame f; 351 SGUISpriteFrame f;
352 f.rectNumber = lowerRightPositions; 352 f.rectNumber = lowerRightPositions;
353 f.textureNumber = 0; 353 f.textureNumber = 0;
354 SGUISprite s; 354 SGUISprite s;
355 s.Frames.push_back(f); 355 s.Frames.push_back(f);
356 s.frameTime = 0; 356 s.frameTime = 0;
357 SpriteBank->getSprites().push_back(s); 357 SpriteBank->getSprites().push_back(s);
358 // add character to font 358 // add character to font
359 SFontArea a; 359 SFontArea a;
360 a.overhang = 0; 360 a.overhang = 0;
361 a.underhang = 0; 361 a.underhang = 0;
362 a.spriteno = lowerRightPositions; 362 a.spriteno = lowerRightPositions;
363 a.width = SpriteBank->getPositions()[lowerRightPositions].getWidth(); 363 a.width = SpriteBank->getPositions()[lowerRightPositions].getWidth();
364 Areas.push_back(a); 364 Areas.push_back(a);
365 // map letter to character 365 // map letter to character
366 wchar_t ch = (wchar_t)(lowerRightPositions + 32); 366 wchar_t ch = (wchar_t)(lowerRightPositions + 32);
367 CharacterMap.set(ch, lowerRightPositions); 367 CharacterMap.set(ch, lowerRightPositions);
368 368
369 ++lowerRightPositions; 369 ++lowerRightPositions;
370 } 370 }
371 else 371 else
372 if (c == colorBackGround) 372 if (c == colorBackGround)
373 image->setPixel(pos.X, pos.Y, colorBackGroundTransparent); 373 image->setPixel(pos.X, pos.Y, colorBackGroundTransparent);
374 } 374 }
375 } 375 }
376} 376}
377 377
378 378
379//! set an Pixel Offset on Drawing ( scale position on width ) 379//! set an Pixel Offset on Drawing ( scale position on width )
380void CGUIFont::setKerningWidth(s32 kerning) 380void CGUIFont::setKerningWidth(s32 kerning)
381{ 381{
382 GlobalKerningWidth = kerning; 382 GlobalKerningWidth = kerning;
383} 383}
384 384
385 385
386//! set an Pixel Offset on Drawing ( scale position on width ) 386//! set an Pixel Offset on Drawing ( scale position on width )
387s32 CGUIFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previousLetter) const 387s32 CGUIFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previousLetter) const
388{ 388{
389 s32 ret = GlobalKerningWidth; 389 s32 ret = GlobalKerningWidth;
390 390
391 if (thisLetter) 391 if (thisLetter)
392 { 392 {
393 ret += Areas[getAreaFromCharacter(*thisLetter)].overhang; 393 ret += Areas[getAreaFromCharacter(*thisLetter)].overhang;
394 394
395 if (previousLetter) 395 if (previousLetter)
396 { 396 {
397 ret += Areas[getAreaFromCharacter(*previousLetter)].underhang; 397 ret += Areas[getAreaFromCharacter(*previousLetter)].underhang;
398 } 398 }
399 } 399 }
400 400
401 return ret; 401 return ret;
402} 402}
403 403
404 404
405//! set an Pixel Offset on Drawing ( scale position on height ) 405//! set an Pixel Offset on Drawing ( scale position on height )
406void CGUIFont::setKerningHeight(s32 kerning) 406void CGUIFont::setKerningHeight(s32 kerning)
407{ 407{
408 GlobalKerningHeight = kerning; 408 GlobalKerningHeight = kerning;
409} 409}
410 410
411 411
412//! set an Pixel Offset on Drawing ( scale position on height ) 412//! set an Pixel Offset on Drawing ( scale position on height )
413s32 CGUIFont::getKerningHeight () const 413s32 CGUIFont::getKerningHeight () const
414{ 414{
415 return GlobalKerningHeight; 415 return GlobalKerningHeight;
416} 416}
417 417
418 418
419//! returns the sprite number from a given character 419//! returns the sprite number from a given character
420u32 CGUIFont::getSpriteNoFromChar(const wchar_t *c) const 420u32 CGUIFont::getSpriteNoFromChar(const wchar_t *c) const
421{ 421{
422 return Areas[getAreaFromCharacter(*c)].spriteno; 422 return Areas[getAreaFromCharacter(*c)].spriteno;
423} 423}
424 424
425 425
426s32 CGUIFont::getAreaFromCharacter(const wchar_t c) const 426s32 CGUIFont::getAreaFromCharacter(const wchar_t c) const
427{ 427{
428 core::map<wchar_t, s32>::Node* n = CharacterMap.find(c); 428 core::map<wchar_t, s32>::Node* n = CharacterMap.find(c);
429 if (n) 429 if (n)
430 return n->getValue(); 430 return n->getValue();
431 else 431 else
432 return WrongCharacter; 432 return WrongCharacter;
433} 433}
434 434
435void CGUIFont::setInvisibleCharacters( const wchar_t *s ) 435void CGUIFont::setInvisibleCharacters( const wchar_t *s )
436{ 436{
437 Invisible = s; 437 Invisible = s;
438} 438}
439 439
440 440
441//! returns the dimension of text 441//! returns the dimension of text
442core::dimension2d<u32> CGUIFont::getDimension(const wchar_t* text) const 442core::dimension2d<u32> CGUIFont::getDimension(const wchar_t* text) const
443{ 443{
444 core::dimension2d<u32> dim(0, 0); 444 core::dimension2d<u32> dim(0, 0);
445 core::dimension2d<u32> thisLine(0, MaxHeight); 445 core::dimension2d<u32> thisLine(0, MaxHeight);
446 446
447 for (const wchar_t* p = text; *p; ++p) 447 for (const wchar_t* p = text; *p; ++p)
448 { 448 {
449 bool lineBreak=false; 449 bool lineBreak=false;
450 if (*p == L'\r') // Mac or Windows breaks 450 if (*p == L'\r') // Mac or Windows breaks
451 { 451 {
452 lineBreak = true; 452 lineBreak = true;
453 if (p[1] == L'\n') // Windows breaks 453 if (p[1] == L'\n') // Windows breaks
454 ++p; 454 ++p;
455 } 455 }
456 else if (*p == L'\n') // Unix breaks 456 else if (*p == L'\n') // Unix breaks
457 { 457 {
458 lineBreak = true; 458 lineBreak = true;
459 } 459 }
460 if (lineBreak) 460 if (lineBreak)
461 { 461 {
462 dim.Height += thisLine.Height; 462 dim.Height += thisLine.Height;
463 if (dim.Width < thisLine.Width) 463 if (dim.Width < thisLine.Width)
464 dim.Width = thisLine.Width; 464 dim.Width = thisLine.Width;
465 thisLine.Width = 0; 465 thisLine.Width = 0;
466 continue; 466 continue;
467 } 467 }
468 468
469 const SFontArea &area = Areas[getAreaFromCharacter(*p)]; 469 const SFontArea &area = Areas[getAreaFromCharacter(*p)];
470 470
471 thisLine.Width += area.underhang; 471 thisLine.Width += area.underhang;
472 thisLine.Width += area.width + area.overhang + GlobalKerningWidth; 472 thisLine.Width += area.width + area.overhang + GlobalKerningWidth;
473 } 473 }
474 474
475 dim.Height += thisLine.Height; 475 dim.Height += thisLine.Height;
476 if (dim.Width < thisLine.Width) 476 if (dim.Width < thisLine.Width)
477 dim.Width = thisLine.Width; 477 dim.Width = thisLine.Width;
478 478
479 return dim; 479 return dim;
480} 480}
481 481
482//! draws some text and clips it to the specified rectangle if wanted 482//! draws some text and clips it to the specified rectangle if wanted
483void CGUIFont::draw(const core::stringw& text, const core::rect<s32>& position, 483void CGUIFont::draw(const core::stringw& text, const core::rect<s32>& position,
484 video::SColor color, 484 video::SColor color,
485 bool hcenter, bool vcenter, const core::rect<s32>* clip 485 bool hcenter, bool vcenter, const core::rect<s32>* clip
486 ) 486 )
487{ 487{
488 if (!Driver || !SpriteBank) 488 if (!Driver || !SpriteBank)
489 return; 489 return;
490 490
491 core::dimension2d<s32> textDimension; // NOTE: don't make this u32 or the >> later on can fail when the dimension width is < position width 491 core::dimension2d<s32> textDimension; // NOTE: don't make this u32 or the >> later on can fail when the dimension width is < position width
492 core::position2d<s32> offset = position.UpperLeftCorner; 492 core::position2d<s32> offset = position.UpperLeftCorner;
493 493
494 if (hcenter || vcenter || clip) 494 if (hcenter || vcenter || clip)
495 textDimension = getDimension(text.c_str()); 495 textDimension = getDimension(text.c_str());
496 496
497 if (hcenter) 497 if (hcenter)
498 offset.X += (position.getWidth() - textDimension.Width) >> 1; 498 offset.X += (position.getWidth() - textDimension.Width) >> 1;
499 499
500 if (vcenter) 500 if (vcenter)
501 offset.Y += (position.getHeight() - textDimension.Height) >> 1; 501 offset.Y += (position.getHeight() - textDimension.Height) >> 1;
502 502
503 if (clip) 503 if (clip)
504 { 504 {
505 core::rect<s32> clippedRect(offset, textDimension); 505 core::rect<s32> clippedRect(offset, textDimension);
506 clippedRect.clipAgainst(*clip); 506 clippedRect.clipAgainst(*clip);
507 if (!clippedRect.isValid()) 507 if (!clippedRect.isValid())
508 return; 508 return;
509 } 509 }
510 510
511 core::array<u32> indices(text.size()); 511 core::array<u32> indices(text.size());
512 core::array<core::position2di> offsets(text.size()); 512 core::array<core::position2di> offsets(text.size());
513 513
514 for(u32 i = 0;i < text.size();i++) 514 for(u32 i = 0;i < text.size();i++)
515 { 515 {
516 wchar_t c = text[i]; 516 wchar_t c = text[i];
517 517
518 bool lineBreak=false; 518 bool lineBreak=false;
519 if ( c == L'\r') // Mac or Windows breaks 519 if ( c == L'\r') // Mac or Windows breaks
520 { 520 {
521 lineBreak = true; 521 lineBreak = true;
522 if ( text[i + 1] == L'\n') // Windows breaks 522 if ( text[i + 1] == L'\n') // Windows breaks
523 c = text[++i]; 523 c = text[++i];
524 } 524 }
525 else if ( c == L'\n') // Unix breaks 525 else if ( c == L'\n') // Unix breaks
526 { 526 {
527 lineBreak = true; 527 lineBreak = true;
528 } 528 }
529 529
530 if (lineBreak) 530 if (lineBreak)
531 { 531 {
532 offset.Y += MaxHeight; 532 offset.Y += MaxHeight;
533 offset.X = position.UpperLeftCorner.X; 533 offset.X = position.UpperLeftCorner.X;
534 534
535 if ( hcenter ) 535 if ( hcenter )
536 { 536 {
537 offset.X += (position.getWidth() - textDimension.Width) >> 1; 537 offset.X += (position.getWidth() - textDimension.Width) >> 1;
538 } 538 }
539 continue; 539 continue;
540 } 540 }
541 541
542 SFontArea& area = Areas[getAreaFromCharacter(c)]; 542 SFontArea& area = Areas[getAreaFromCharacter(c)];
543 543
544 offset.X += area.underhang; 544 offset.X += area.underhang;
545 if ( Invisible.findFirst ( c ) < 0 ) 545 if ( Invisible.findFirst ( c ) < 0 )
546 { 546 {
547 indices.push_back(area.spriteno); 547 indices.push_back(area.spriteno);
548 offsets.push_back(offset); 548 offsets.push_back(offset);
549 } 549 }
550 550
551 offset.X += area.width + area.overhang + GlobalKerningWidth; 551 offset.X += area.width + area.overhang + GlobalKerningWidth;
552 } 552 }
553 553
554 SpriteBank->draw2DSpriteBatch(indices, offsets, clip, color); 554 SpriteBank->draw2DSpriteBatch(indices, offsets, clip, color);
555} 555}
556 556
557 557
558//! Calculates the index of the character in the text which is on a specific position. 558//! Calculates the index of the character in the text which is on a specific position.
559s32 CGUIFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const 559s32 CGUIFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
560{ 560{
561 s32 x = 0; 561 s32 x = 0;
562 s32 idx = 0; 562 s32 idx = 0;
563 563
564 while (text[idx]) 564 while (text[idx])
565 { 565 {
566 const SFontArea& a = Areas[getAreaFromCharacter(text[idx])]; 566 const SFontArea& a = Areas[getAreaFromCharacter(text[idx])];
567 567
568 x += a.width + a.overhang + a.underhang + GlobalKerningWidth; 568 x += a.width + a.overhang + a.underhang + GlobalKerningWidth;
569 569
570 if (x >= pixel_x) 570 if (x >= pixel_x)
571 return idx; 571 return idx;
572 572
573 ++idx; 573 ++idx;
574 } 574 }
575 575
576 return -1; 576 return -1;
577} 577}
578 578
579 579
580IGUISpriteBank* CGUIFont::getSpriteBank() const 580IGUISpriteBank* CGUIFont::getSpriteBank() const
581{ 581{
582 return SpriteBank; 582 return SpriteBank;
583} 583}
584 584
585} // end namespace gui 585} // end namespace gui
586} // end namespace irr 586} // end namespace irr
587 587
588#endif // _IRR_COMPILE_WITH_GUI_ 588#endif // _IRR_COMPILE_WITH_GUI_
589 589