aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/tools/IrrFontTool/newFontTool/CFontTool.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/irrlicht-1.8/tools/IrrFontTool/newFontTool/CFontTool.cpp')
-rw-r--r--libraries/irrlicht-1.8/tools/IrrFontTool/newFontTool/CFontTool.cpp1602
1 files changed, 801 insertions, 801 deletions
diff --git a/libraries/irrlicht-1.8/tools/IrrFontTool/newFontTool/CFontTool.cpp b/libraries/irrlicht-1.8/tools/IrrFontTool/newFontTool/CFontTool.cpp
index 780e9b0..7579d5d 100644
--- a/libraries/irrlicht-1.8/tools/IrrFontTool/newFontTool/CFontTool.cpp
+++ b/libraries/irrlicht-1.8/tools/IrrFontTool/newFontTool/CFontTool.cpp
@@ -1,801 +1,801 @@
1#include "CFontTool.h" 1#include "CFontTool.h"
2#include "IXMLWriter.h" 2#include "IXMLWriter.h"
3 3
4using namespace irr; 4using namespace irr;
5 5
6const int fontsizes[] = {4,6,8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,56,68,72,0}; 6const int fontsizes[] = {4,6,8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,56,68,72,0};
7 7
8inline u32 getTextureSizeFromSurfaceSize(u32 size) 8inline u32 getTextureSizeFromSurfaceSize(u32 size)
9{ 9{
10 u32 ts = 0x01; 10 u32 ts = 0x01;
11 while(ts < size) 11 while(ts < size)
12 ts <<= 1; 12 ts <<= 1;
13 13
14 return ts; 14 return ts;
15} 15}
16 16
17// windows specific 17// windows specific
18#ifdef _IRR_WINDOWS_ 18#ifdef _IRR_WINDOWS_
19 19
20 const DWORD charsets[] = { ANSI_CHARSET, DEFAULT_CHARSET, OEM_CHARSET, BALTIC_CHARSET, GB2312_CHARSET, CHINESEBIG5_CHARSET, 20 const DWORD charsets[] = { ANSI_CHARSET, DEFAULT_CHARSET, OEM_CHARSET, BALTIC_CHARSET, GB2312_CHARSET, CHINESEBIG5_CHARSET,
21 EASTEUROPE_CHARSET, GREEK_CHARSET, HANGUL_CHARSET, MAC_CHARSET, RUSSIAN_CHARSET, 21 EASTEUROPE_CHARSET, GREEK_CHARSET, HANGUL_CHARSET, MAC_CHARSET, RUSSIAN_CHARSET,
22 SHIFTJIS_CHARSET, SYMBOL_CHARSET, TURKISH_CHARSET, VIETNAMESE_CHARSET, JOHAB_CHARSET, 22 SHIFTJIS_CHARSET, SYMBOL_CHARSET, TURKISH_CHARSET, VIETNAMESE_CHARSET, JOHAB_CHARSET,
23 ARABIC_CHARSET, HEBREW_CHARSET, THAI_CHARSET, 0}; 23 ARABIC_CHARSET, HEBREW_CHARSET, THAI_CHARSET, 0};
24 24
25 const wchar_t *setnames[] = {L"ANSI", L"All Available", L"OEM", L"Baltic", L"Chinese Simplified", L"Chinese Traditional", 25 const wchar_t *setnames[] = {L"ANSI", L"All Available", L"OEM", L"Baltic", L"Chinese Simplified", L"Chinese Traditional",
26 L"Eastern European", L"Greek", L"Hangul", L"Macintosh", L"Russian", 26 L"Eastern European", L"Greek", L"Hangul", L"Macintosh", L"Russian",
27 L"Japanese", L"Symbol", L"Turkish", L"Vietnamese", L"Johab", 27 L"Japanese", L"Symbol", L"Turkish", L"Vietnamese", L"Johab",
28 L"Arabic", L"Hebrew", L"Thai", 0}; 28 L"Arabic", L"Hebrew", L"Thai", 0};
29 29
30 // callback for adding font names 30 // callback for adding font names
31 int CALLBACK EnumFontFamExProc( ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme, 31 int CALLBACK EnumFontFamExProc( ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme,
32 DWORD FontType, LPARAM lParam) 32 DWORD FontType, LPARAM lParam)
33 { 33 {
34 CFontTool* t = (CFontTool*) lParam; 34 CFontTool* t = (CFontTool*) lParam;
35 t->FontNames.push_back( core::stringw(lpelfe->elfFullName)); 35 t->FontNames.push_back( core::stringw(lpelfe->elfFullName));
36 return 1; 36 return 1;
37 } 37 }
38 38
39 // 39 //
40 // Constructor 40 // Constructor
41 // 41 //
42 42
43 CFontTool::CFontTool(IrrlichtDevice* device) : FontSizes(fontsizes), 43 CFontTool::CFontTool(IrrlichtDevice* device) : FontSizes(fontsizes),
44 Device(device), UseAlphaChannel(false), 44 Device(device), UseAlphaChannel(false),
45 // win specific 45 // win specific
46 dc(0) 46 dc(0)
47 { 47 {
48 // init display context 48 // init display context
49 dc = CreateDC(L"DISPLAY", L"DISPLAY", 0 ,0 ); 49 dc = CreateDC(L"DISPLAY", L"DISPLAY", 0 ,0 );
50 50
51 // populate list of available character set names 51 // populate list of available character set names
52 for (int i=0; setnames[i] != 0; ++i) 52 for (int i=0; setnames[i] != 0; ++i)
53 CharSets.push_back( core::stringw(setnames[i])); 53 CharSets.push_back( core::stringw(setnames[i]));
54 54
55 selectCharSet(0); 55 selectCharSet(0);
56 } 56 }
57 57
58 void CFontTool::selectCharSet(u32 currentCharSet) 58 void CFontTool::selectCharSet(u32 currentCharSet)
59 { 59 {
60 if ( currentCharSet >= CharSets.size() ) 60 if ( currentCharSet >= CharSets.size() )
61 return; 61 return;
62 62
63 LOGFONTW lf; 63 LOGFONTW lf;
64 lf.lfFaceName[0] = L'\0'; 64 lf.lfFaceName[0] = L'\0';
65 lf.lfCharSet = (BYTE) charsets[currentCharSet]; 65 lf.lfCharSet = (BYTE) charsets[currentCharSet];
66 // HRESULT hr; // no error checking(!) 66 // HRESULT hr; // no error checking(!)
67 67
68 // clear font list 68 // clear font list
69 FontNames.clear(); 69 FontNames.clear();
70 70
71 // create list of available fonts 71 // create list of available fonts
72 EnumFontFamiliesExW( dc, (LPLOGFONTW) &lf, (FONTENUMPROCW) EnumFontFamExProc, (LPARAM) this, 0); 72 EnumFontFamiliesExW( dc, (LPLOGFONTW) &lf, (FONTENUMPROCW) EnumFontFamExProc, (LPARAM) this, 0);
73 } 73 }
74 74
75 bool CFontTool::makeBitmapFont(u32 fontIndex, u32 charsetIndex, s32 fontSize, u32 textureWidth, u32 textureHeight, bool bold, bool italic, bool aa, bool alpha) 75 bool CFontTool::makeBitmapFont(u32 fontIndex, u32 charsetIndex, s32 fontSize, u32 textureWidth, u32 textureHeight, bool bold, bool italic, bool aa, bool alpha)
76 { 76 {
77 if (fontIndex >= FontNames.size() || charsetIndex >= CharSets.size() ) 77 if (fontIndex >= FontNames.size() || charsetIndex >= CharSets.size() )
78 return false; 78 return false;
79 79
80 UseAlphaChannel = alpha; 80 UseAlphaChannel = alpha;
81 u32 currentImage = 0; 81 u32 currentImage = 0;
82 82
83 // create the font 83 // create the font
84 HFONT font = CreateFontW( 84 HFONT font = CreateFontW(
85 -MulDiv(fontSize, GetDeviceCaps(dc, LOGPIXELSY), 72), 0, 85 -MulDiv(fontSize, GetDeviceCaps(dc, LOGPIXELSY), 72), 0,
86 0,0, 86 0,0,
87 bold ? FW_BOLD : 0, 87 bold ? FW_BOLD : 0,
88 italic, 0,0, charsets[charsetIndex], 0,0, 88 italic, 0,0, charsets[charsetIndex], 0,0,
89 aa ? ANTIALIASED_QUALITY : 0, 89 aa ? ANTIALIASED_QUALITY : 0,
90 0, FontNames[fontIndex].c_str() ); 90 0, FontNames[fontIndex].c_str() );
91 91
92 if (!font) 92 if (!font)
93 return false; 93 return false;
94 94
95 SelectObject(dc, font); 95 SelectObject(dc, font);
96 SetTextAlign (dc,TA_LEFT | TA_TOP | TA_NOUPDATECP); 96 SetTextAlign (dc,TA_LEFT | TA_TOP | TA_NOUPDATECP);
97 97
98 // get rid of the current textures/images 98 // get rid of the current textures/images
99 for (u32 i=0; i<currentTextures.size(); ++i) 99 for (u32 i=0; i<currentTextures.size(); ++i)
100 currentTextures[i]->drop(); 100 currentTextures[i]->drop();
101 currentTextures.clear(); 101 currentTextures.clear();
102 102
103 for (u32 i=0; i<currentImages.size(); ++i) 103 for (u32 i=0; i<currentImages.size(); ++i)
104 currentImages[i]->drop(); 104 currentImages[i]->drop();
105 currentImages.clear(); 105 currentImages.clear();
106 106
107 // clear current image mappings 107 // clear current image mappings
108 CharMap.clear(); 108 CharMap.clear();
109 // clear array 109 // clear array
110 Areas.clear(); 110 Areas.clear();
111 111
112 // get information about this font's unicode ranges. 112 // get information about this font's unicode ranges.
113 s32 size = GetFontUnicodeRanges( dc, 0); 113 s32 size = GetFontUnicodeRanges( dc, 0);
114 c8 *buf = new c8[size]; 114 c8 *buf = new c8[size];
115 LPGLYPHSET glyphs = (LPGLYPHSET)buf; 115 LPGLYPHSET glyphs = (LPGLYPHSET)buf;
116 116
117 GetFontUnicodeRanges( dc, glyphs); 117 GetFontUnicodeRanges( dc, glyphs);
118 118
119 // s32 TotalCharCount = glyphs->cGlyphsSupported; 119 // s32 TotalCharCount = glyphs->cGlyphsSupported;
120 120
121 s32 currentx=0, currenty=0, maxy=0; 121 s32 currentx=0, currenty=0, maxy=0;
122 122
123 for (u32 range=0; range < glyphs->cRanges; range++) 123 for (u32 range=0; range < glyphs->cRanges; range++)
124 { 124 {
125 WCRANGE* current = &glyphs->ranges[range]; 125 WCRANGE* current = &glyphs->ranges[range];
126 126
127 //maxy=0; 127 //maxy=0;
128 128
129 // loop through each glyph and write its size and position 129 // loop through each glyph and write its size and position
130 for (s32 ch=current->wcLow; ch< current->wcLow + current->cGlyphs; ch++) 130 for (s32 ch=current->wcLow; ch< current->wcLow + current->cGlyphs; ch++)
131 { 131 {
132 wchar_t currentchar = ch; 132 wchar_t currentchar = ch;
133 133
134 if ( IsDBCSLeadByte((BYTE) ch)) 134 if ( IsDBCSLeadByte((BYTE) ch))
135 continue; // surragate pairs unsupported 135 continue; // surragate pairs unsupported
136 136
137 // get the dimensions 137 // get the dimensions
138 SIZE size; 138 SIZE size;
139 ABC abc; 139 ABC abc;
140 GetTextExtentPoint32W(dc, &currentchar, 1, &size); 140 GetTextExtentPoint32W(dc, &currentchar, 1, &size);
141 SFontArea fa; 141 SFontArea fa;
142 fa.underhang = 0; 142 fa.underhang = 0;
143 fa.overhang = 0; 143 fa.overhang = 0;
144 144
145 if (GetCharABCWidthsW(dc, currentchar, currentchar, &abc)) // for unicode fonts, get overhang, underhang, width 145 if (GetCharABCWidthsW(dc, currentchar, currentchar, &abc)) // for unicode fonts, get overhang, underhang, width
146 { 146 {
147 size.cx = abc.abcB; 147 size.cx = abc.abcB;
148 fa.underhang = abc.abcA; 148 fa.underhang = abc.abcA;
149 fa.overhang = abc.abcC; 149 fa.overhang = abc.abcC;
150 150
151 if (abc.abcB-abc.abcA+abc.abcC<1) 151 if (abc.abcB-abc.abcA+abc.abcC<1)
152 continue; // nothing of width 0 152 continue; // nothing of width 0
153 } 153 }
154 if (size.cy < 1) 154 if (size.cy < 1)
155 continue; 155 continue;
156 156
157 //GetGlyphOutline(dc, currentchar, GGO_METRICS, &gm, 0, 0, 0); 157 //GetGlyphOutline(dc, currentchar, GGO_METRICS, &gm, 0, 0, 0);
158 158
159 //size.cx++; size.cy++; 159 //size.cx++; size.cy++;
160 160
161 // wrap around? 161 // wrap around?
162 if (currentx + size.cx > (s32) textureWidth) 162 if (currentx + size.cx > (s32) textureWidth)
163 { 163 {
164 currenty += maxy; 164 currenty += maxy;
165 currentx = 0; 165 currentx = 0;
166 if ((u32)(currenty + maxy) > textureHeight) 166 if ((u32)(currenty + maxy) > textureHeight)
167 { 167 {
168 currentImage++; // increase Image count 168 currentImage++; // increase Image count
169 currenty=0; 169 currenty=0;
170 } 170 }
171 maxy = 0; 171 maxy = 0;
172 } 172 }
173 // add this char dimension to the current map 173 // add this char dimension to the current map
174 174
175 fa.rectangle = core::rect<s32>(currentx, currenty, currentx + size.cx, currenty + size.cy); 175 fa.rectangle = core::rect<s32>(currentx, currenty, currentx + size.cx, currenty + size.cy);
176 fa.sourceimage = currentImage; 176 fa.sourceimage = currentImage;
177 177
178 CharMap.insert(currentchar, Areas.size()); 178 CharMap.insert(currentchar, Areas.size());
179 Areas.push_back( fa ); 179 Areas.push_back( fa );
180 180
181 currentx += size.cx +1; 181 currentx += size.cx +1;
182 182
183 if (size.cy+1 > maxy) 183 if (size.cy+1 > maxy)
184 maxy = size.cy+1; 184 maxy = size.cy+1;
185 } 185 }
186 } 186 }
187 currenty += maxy; 187 currenty += maxy;
188 188
189 u32 lastTextureHeight = getTextureSizeFromSurfaceSize(currenty); 189 u32 lastTextureHeight = getTextureSizeFromSurfaceSize(currenty);
190 190
191 // delete the glyph set 191 // delete the glyph set
192 delete [] buf; 192 delete [] buf;
193 193
194 currentImages.set_used(currentImage+1); 194 currentImages.set_used(currentImage+1);
195 currentTextures.set_used(currentImage+1); 195 currentTextures.set_used(currentImage+1);
196 196
197 for (currentImage=0; currentImage < currentImages.size(); ++currentImage) 197 for (currentImage=0; currentImage < currentImages.size(); ++currentImage)
198 { 198 {
199 core::stringc logmsg = "Creating image "; 199 core::stringc logmsg = "Creating image ";
200 logmsg += (s32) (currentImage+1); 200 logmsg += (s32) (currentImage+1);
201 logmsg += " of "; 201 logmsg += " of ";
202 logmsg += (s32) currentImages.size(); 202 logmsg += (s32) currentImages.size();
203 Device->getLogger()->log(logmsg.c_str()); 203 Device->getLogger()->log(logmsg.c_str());
204 // no need for a huge final texture 204 // no need for a huge final texture
205 u32 texHeight = textureHeight; 205 u32 texHeight = textureHeight;
206 if (currentImage == currentImages.size()-1 ) 206 if (currentImage == currentImages.size()-1 )
207 texHeight = lastTextureHeight; 207 texHeight = lastTextureHeight;
208 208
209 // make a new bitmap 209 // make a new bitmap
210 HBITMAP bmp = CreateCompatibleBitmap(dc, textureWidth, texHeight); 210 HBITMAP bmp = CreateCompatibleBitmap(dc, textureWidth, texHeight);
211 HDC bmpdc = CreateCompatibleDC(dc); 211 HDC bmpdc = CreateCompatibleDC(dc);
212 212
213 LOGBRUSH lbrush; 213 LOGBRUSH lbrush;
214 lbrush.lbColor = RGB(0,0,0); 214 lbrush.lbColor = RGB(0,0,0);
215 lbrush.lbHatch = 0; 215 lbrush.lbHatch = 0;
216 lbrush.lbStyle = BS_SOLID; 216 lbrush.lbStyle = BS_SOLID;
217 217
218 HBRUSH brush = CreateBrushIndirect(&lbrush); 218 HBRUSH brush = CreateBrushIndirect(&lbrush);
219 HPEN pen = CreatePen(PS_NULL, 0, 0); 219 HPEN pen = CreatePen(PS_NULL, 0, 0);
220 220
221 HGDIOBJ oldbmp = SelectObject(bmpdc, bmp); 221 HGDIOBJ oldbmp = SelectObject(bmpdc, bmp);
222 HGDIOBJ oldbmppen = SelectObject(bmpdc, pen); 222 HGDIOBJ oldbmppen = SelectObject(bmpdc, pen);
223 HGDIOBJ oldbmpbrush = SelectObject(bmpdc, brush); 223 HGDIOBJ oldbmpbrush = SelectObject(bmpdc, brush);
224 HGDIOBJ oldbmpfont = SelectObject(bmpdc, font); 224 HGDIOBJ oldbmpfont = SelectObject(bmpdc, font);
225 225
226 SetTextColor(bmpdc, RGB(255,255,255)); 226 SetTextColor(bmpdc, RGB(255,255,255));
227 227
228 Rectangle(bmpdc, 0,0,textureWidth,texHeight); 228 Rectangle(bmpdc, 0,0,textureWidth,texHeight);
229 SetBkMode(bmpdc, TRANSPARENT); 229 SetBkMode(bmpdc, TRANSPARENT);
230 230
231 // draw the letters... 231 // draw the letters...
232 232
233 // iterate through the tree 233 // iterate through the tree
234 core::map<wchar_t, u32>::Iterator it = CharMap.getIterator(); 234 core::map<wchar_t, u32>::Iterator it = CharMap.getIterator();
235 while (!it.atEnd()) 235 while (!it.atEnd())
236 { 236 {
237 s32 currentArea = (*it).getValue(); 237 s32 currentArea = (*it).getValue();
238 wchar_t wch = (*it).getKey(); 238 wchar_t wch = (*it).getKey();
239 // sloppy but I couldnt be bothered rewriting it 239 // sloppy but I couldnt be bothered rewriting it
240 if (Areas[currentArea].sourceimage == currentImage) 240 if (Areas[currentArea].sourceimage == currentImage)
241 { 241 {
242 // draw letter 242 // draw letter
243 s32 sx = Areas[currentArea].rectangle.UpperLeftCorner.X - Areas[currentArea].underhang; 243 s32 sx = Areas[currentArea].rectangle.UpperLeftCorner.X - Areas[currentArea].underhang;
244 TextOutW(bmpdc, sx, Areas[currentArea].rectangle.UpperLeftCorner.Y, &wch, 1); 244 TextOutW(bmpdc, sx, Areas[currentArea].rectangle.UpperLeftCorner.Y, &wch, 1);
245 245
246 // if ascii font... 246 // if ascii font...
247 //SetPixel(bmpdc, Areas[currentArea].rectangle.UpperLeftCorner.X, Areas[currentArea].rectangle.UpperLeftCorner.Y, RGB(255,255,0));// left upper corner mark 247 //SetPixel(bmpdc, Areas[currentArea].rectangle.UpperLeftCorner.X, Areas[currentArea].rectangle.UpperLeftCorner.Y, RGB(255,255,0));// left upper corner mark
248 } 248 }
249 it++; 249 it++;
250 } 250 }
251 251
252 // copy the font bitmap into a new irrlicht image 252 // copy the font bitmap into a new irrlicht image
253 BITMAP b; 253 BITMAP b;
254 PBITMAPINFO pbmi; 254 PBITMAPINFO pbmi;
255 WORD cClrBits; 255 WORD cClrBits;
256 u32 cformat; 256 u32 cformat;
257 257
258 // Retrieve the bitmap color format, width, and height. 258 // Retrieve the bitmap color format, width, and height.
259 GetObject(bmp, sizeof(BITMAP), (LPSTR)&b); 259 GetObject(bmp, sizeof(BITMAP), (LPSTR)&b);
260 260
261 // Convert the color format to a count of bits. 261 // Convert the color format to a count of bits.
262 cClrBits = (WORD)(b.bmPlanes * b.bmBitsPixel); 262 cClrBits = (WORD)(b.bmPlanes * b.bmBitsPixel);
263 263
264 if (cClrBits <= 8) // we're not supporting these 264 if (cClrBits <= 8) // we're not supporting these
265 cformat = -1; 265 cformat = -1;
266 else if (cClrBits <= 16) 266 else if (cClrBits <= 16)
267 cformat = video::ECF_A1R5G5B5; 267 cformat = video::ECF_A1R5G5B5;
268 else if (cClrBits <= 24) 268 else if (cClrBits <= 24)
269 cformat = video::ECF_R8G8B8; 269 cformat = video::ECF_R8G8B8;
270 else 270 else
271 cformat = video::ECF_A8R8G8B8; 271 cformat = video::ECF_A8R8G8B8;
272 272
273 pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 273 pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
274 sizeof(BITMAPINFOHEADER)); 274 sizeof(BITMAPINFOHEADER));
275 275
276 // Initialize the fields in the BITMAPINFO structure. 276 // Initialize the fields in the BITMAPINFO structure.
277 277
278 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 278 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
279 pbmi->bmiHeader.biWidth = b.bmWidth; 279 pbmi->bmiHeader.biWidth = b.bmWidth;
280 pbmi->bmiHeader.biHeight = b.bmHeight; 280 pbmi->bmiHeader.biHeight = b.bmHeight;
281 pbmi->bmiHeader.biPlanes = b.bmPlanes; 281 pbmi->bmiHeader.biPlanes = b.bmPlanes;
282 pbmi->bmiHeader.biBitCount = b.bmBitsPixel; 282 pbmi->bmiHeader.biBitCount = b.bmBitsPixel;
283 283
284 // If the bitmap is not compressed, set the BI_RGB flag. 284 // If the bitmap is not compressed, set the BI_RGB flag.
285 pbmi->bmiHeader.biCompression = BI_RGB; 285 pbmi->bmiHeader.biCompression = BI_RGB;
286 286
287 // Compute the number of bytes in the array of color 287 // Compute the number of bytes in the array of color
288 // indices and store the result in biSizeImage. 288 // indices and store the result in biSizeImage.
289 // For Windows NT, the width must be DWORD aligned unless 289 // For Windows NT, the width must be DWORD aligned unless
290 // the bitmap is RLE compressed. This example shows this. 290 // the bitmap is RLE compressed. This example shows this.
291 // For Windows 95/98/Me, the width must be WORD aligned unless the 291 // For Windows 95/98/Me, the width must be WORD aligned unless the
292 // bitmap is RLE compressed. 292 // bitmap is RLE compressed.
293 pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 293 pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
294 * pbmi->bmiHeader.biHeight; 294 * pbmi->bmiHeader.biHeight;
295 // Set biClrImportant to 0, indicating that all of the 295 // Set biClrImportant to 0, indicating that all of the
296 // device colors are important. 296 // device colors are important.
297 pbmi->bmiHeader.biClrImportant = 0; 297 pbmi->bmiHeader.biClrImportant = 0;
298 298
299 LPBYTE lpBits; // memory pointer 299 LPBYTE lpBits; // memory pointer
300 300
301 PBITMAPINFOHEADER pbih = (PBITMAPINFOHEADER) pbmi; 301 PBITMAPINFOHEADER pbih = (PBITMAPINFOHEADER) pbmi;
302 lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage); 302 lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
303 303
304 GetDIBits(dc, bmp, 0, (WORD) pbih->biHeight, lpBits, pbmi, DIB_RGB_COLORS); 304 GetDIBits(dc, bmp, 0, (WORD) pbih->biHeight, lpBits, pbmi, DIB_RGB_COLORS);
305 305
306 // DEBUG- copy to clipboard 306 // DEBUG- copy to clipboard
307 //OpenClipboard(hWnd); 307 //OpenClipboard(hWnd);
308 //EmptyClipboard(); 308 //EmptyClipboard();
309 //SetClipboardData(CF_BITMAP, bmp); 309 //SetClipboardData(CF_BITMAP, bmp);
310 //CloseClipboard(); 310 //CloseClipboard();
311 311
312 // flip bitmap 312 // flip bitmap
313 s32 rowsize = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8; 313 s32 rowsize = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8;
314 c8 *row = new c8[rowsize]; 314 c8 *row = new c8[rowsize];
315 for (s32 i=0; i < (pbih->biHeight/2); ++i) 315 for (s32 i=0; i < (pbih->biHeight/2); ++i)
316 { 316 {
317 // grab a row 317 // grab a row
318 memcpy(row, lpBits + (rowsize * i), rowsize); 318 memcpy(row, lpBits + (rowsize * i), rowsize);
319 // swap row 319 // swap row
320 memcpy(lpBits + (rowsize * i), lpBits + ((pbih->biHeight-1 -i) * rowsize ) , rowsize); 320 memcpy(lpBits + (rowsize * i), lpBits + ((pbih->biHeight-1 -i) * rowsize ) , rowsize);
321 memcpy(lpBits + ((pbih->biHeight-1 -i) * rowsize ), row , rowsize); 321 memcpy(lpBits + ((pbih->biHeight-1 -i) * rowsize ), row , rowsize);
322 } 322 }
323 323
324 bool ret = false; 324 bool ret = false;
325 325
326 if (cformat == video::ECF_A8R8G8B8) 326 if (cformat == video::ECF_A8R8G8B8)
327 { 327 {
328 // in this case the font should have an alpha channel, but since windows doesn't draw one 328 // in this case the font should have an alpha channel, but since windows doesn't draw one
329 // we have to set one manually by going through all the pixels.. *sigh* 329 // we have to set one manually by going through all the pixels.. *sigh*
330 330
331 u8* m; 331 u8* m;
332 for (m = lpBits; m < lpBits + pbih->biSizeImage; m+=4) 332 for (m = lpBits; m < lpBits + pbih->biSizeImage; m+=4)
333 { 333 {
334 if (UseAlphaChannel) 334 if (UseAlphaChannel)
335 { 335 {
336 if (m[0] > 0) // pixel has colour 336 if (m[0] > 0) // pixel has colour
337 { 337 {
338 m[3]=m[0]; // set alpha 338 m[3]=m[0]; // set alpha
339 m[0]=m[1]=m[2] = 255; // everything else is full 339 m[0]=m[1]=m[2] = 255; // everything else is full
340 } 340 }
341 } 341 }
342 else 342 else
343 m[3]=255; // all pixels are full alpha 343 m[3]=255; // all pixels are full alpha
344 } 344 }
345 345
346 } 346 }
347 else if (cformat == video::ECF_A1R5G5B5) 347 else if (cformat == video::ECF_A1R5G5B5)
348 { 348 {
349 u8* m; 349 u8* m;
350 for (m = lpBits; m < lpBits + pbih->biSizeImage; m+=2) 350 for (m = lpBits; m < lpBits + pbih->biSizeImage; m+=2)
351 { 351 {
352 WORD *p = (WORD*)m; 352 WORD *p = (WORD*)m;
353 if (m[0] > 0 || !UseAlphaChannel) // alpha should be set 353 if (m[0] > 0 || !UseAlphaChannel) // alpha should be set
354 *p |= 0x8000; // set alpha bit 354 *p |= 0x8000; // set alpha bit
355 } 355 }
356 } 356 }
357 else 357 else
358 { 358 {
359 cformat = -1; 359 cformat = -1;
360 } 360 }
361 361
362 // make a texture from the image 362 // make a texture from the image
363 if (cformat != -1) 363 if (cformat != -1)
364 { 364 {
365 // turn mip-mapping off 365 // turn mip-mapping off
366 bool b = Device->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); 366 bool b = Device->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
367 currentImages[currentImage] = Device->getVideoDriver()->createImageFromData((video::ECOLOR_FORMAT)cformat, core::dimension2d<u32>(textureWidth,texHeight), (void*)lpBits); 367 currentImages[currentImage] = Device->getVideoDriver()->createImageFromData((video::ECOLOR_FORMAT)cformat, core::dimension2d<u32>(textureWidth,texHeight), (void*)lpBits);
368 Device->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS,b); 368 Device->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS,b);
369 } 369 }
370 else 370 else
371 { 371 {
372 Device->getLogger()->log("Couldn't create font, your pixel format is unsupported."); 372 Device->getLogger()->log("Couldn't create font, your pixel format is unsupported.");
373 } 373 }
374 374
375 // free memory and windows resources 375 // free memory and windows resources
376 // sloppy I know, but I only intended to create one image at first. 376 // sloppy I know, but I only intended to create one image at first.
377 delete [] row; 377 delete [] row;
378 LocalFree(pbmi); 378 LocalFree(pbmi);
379 GlobalFree(lpBits); 379 GlobalFree(lpBits);
380 DeleteDC(bmpdc); 380 DeleteDC(bmpdc);
381 DeleteObject(brush); 381 DeleteObject(brush);
382 DeleteObject(pen); 382 DeleteObject(pen);
383 DeleteObject(bmp); 383 DeleteObject(bmp);
384 384
385 if (currentImages[currentImage]) 385 if (currentImages[currentImage])
386 { 386 {
387 // add texture 387 // add texture
388 currentTextures[currentImage] = Device->getVideoDriver()->addTexture("GUIFontImage",currentImages[currentImage]); 388 currentTextures[currentImage] = Device->getVideoDriver()->addTexture("GUIFontImage",currentImages[currentImage]);
389 currentTextures[currentImage]->grab(); 389 currentTextures[currentImage]->grab();
390 } 390 }
391 else 391 else
392 { 392 {
393 Device->getLogger()->log("Something went wrong, aborting."); 393 Device->getLogger()->log("Something went wrong, aborting.");
394 // drop all images 394 // drop all images
395 DeleteObject(font); 395 DeleteObject(font);
396 return false; 396 return false;
397 } 397 }
398 } // looping through each texture 398 } // looping through each texture
399 DeleteObject(font); 399 DeleteObject(font);
400 return true; 400 return true;
401 } 401 }
402 402
403#else 403#else
404 404
405 CFontTool::CFontTool(IrrlichtDevice *device) : FontSizes(fontsizes), Device(device), UseAlphaChannel(false) 405 CFontTool::CFontTool(IrrlichtDevice *device) : FontSizes(fontsizes), Device(device), UseAlphaChannel(false)
406 { 406 {
407 if (!XftInitFtLibrary()) 407 if (!XftInitFtLibrary())
408 { 408 {
409 core::stringc logmsg = "XFT not found\n"; 409 core::stringc logmsg = "XFT not found\n";
410 Device->getLogger()->log(logmsg.c_str()); 410 Device->getLogger()->log(logmsg.c_str());
411 exit(EXIT_FAILURE); 411 exit(EXIT_FAILURE);
412 } 412 }
413 413
414 /* Get a list of the font foundries, storing them in a set to sort */ 414 /* Get a list of the font foundries, storing them in a set to sort */
415 std::set<core::stringw> foundries; 415 std::set<core::stringw> foundries;
416 Display* display = (Display*)Device->getVideoDriver()->getExposedVideoData().OpenGLLinux.X11Display; 416 Display* display = (Display*)Device->getVideoDriver()->getExposedVideoData().OpenGLLinux.X11Display;
417 XftFontSet* fonts = XftListFonts(display, DefaultScreen(display), 0, XFT_FOUNDRY, 0); 417 XftFontSet* fonts = XftListFonts(display, DefaultScreen(display), 0, XFT_FOUNDRY, 0);
418 for (int i = 0; i < fonts->nfont; i++) 418 for (int i = 0; i < fonts->nfont; i++)
419 { 419 {
420 char *foundry; 420 char *foundry;
421 XftPatternGetString(fonts->fonts[i], XFT_FOUNDRY, 0, &foundry); 421 XftPatternGetString(fonts->fonts[i], XFT_FOUNDRY, 0, &foundry);
422 core::stringw tmp(foundry); 422 core::stringw tmp(foundry);
423 foundries.insert(tmp); 423 foundries.insert(tmp);
424 } 424 }
425 XftFontSetDestroy(fonts); 425 XftFontSetDestroy(fonts);
426 426
427 /* Copy the sorted list into the array */ 427 /* Copy the sorted list into the array */
428 CharSets.clear(); 428 CharSets.clear();
429 for (std::set<core::stringw>::iterator i = foundries.begin(); i != foundries.end(); i++) 429 for (std::set<core::stringw>::iterator i = foundries.begin(); i != foundries.end(); i++)
430 CharSets.push_back((*i).c_str()); 430 CharSets.push_back((*i).c_str());
431 selectCharSet(0); 431 selectCharSet(0);
432 } 432 }
433 433
434 /* Note: There must be some trick for using strings as pattern parameters to XftListFonts because 434 /* Note: There must be some trick for using strings as pattern parameters to XftListFonts because
435 no matter how I specify a string, I end up with an intermittent segfault. Since XftFontList is 435 no matter how I specify a string, I end up with an intermittent segfault. Since XftFontList is
436 just calling FcFontList, that's what I'll do too since that works OK */ 436 just calling FcFontList, that's what I'll do too since that works OK */
437 void CFontTool::selectCharSet(u32 currentCharSet) 437 void CFontTool::selectCharSet(u32 currentCharSet)
438 { 438 {
439 /* Get a list of the font families, storing them in a set to sort */ 439 /* Get a list of the font families, storing them in a set to sort */
440 char foundry[256]; 440 char foundry[256];
441 sprintf(&foundry[0],"%ls",CharSets[currentCharSet].c_str()); 441 sprintf(&foundry[0],"%ls",CharSets[currentCharSet].c_str());
442 std::set<core::stringw> families; 442 std::set<core::stringw> families;
443 XftPattern *pattern = FcPatternCreate(); 443 XftPattern *pattern = FcPatternCreate();
444 XftPatternAddString(pattern, FC_FOUNDRY, &foundry[0]); 444 XftPatternAddString(pattern, FC_FOUNDRY, &foundry[0]);
445 XftObjectSet *objectset = FcObjectSetCreate(); 445 XftObjectSet *objectset = FcObjectSetCreate();
446 XftObjectSetAdd(objectset, XFT_FOUNDRY); 446 XftObjectSetAdd(objectset, XFT_FOUNDRY);
447 XftObjectSetAdd(objectset, XFT_FAMILY); 447 XftObjectSetAdd(objectset, XFT_FAMILY);
448 FcFontSet *fonts = FcFontList(NULL, pattern, objectset); 448 FcFontSet *fonts = FcFontList(NULL, pattern, objectset);
449 449
450 for (int i = 0; i < fonts->nfont; i++) 450 for (int i = 0; i < fonts->nfont; i++)
451 { 451 {
452 char* ptr; 452 char* ptr;
453 XftPatternGetString(fonts->fonts[i], XFT_FAMILY, 0, &ptr); 453 XftPatternGetString(fonts->fonts[i], XFT_FAMILY, 0, &ptr);
454 core::stringw family(ptr); 454 core::stringw family(ptr);
455 families.insert(family); 455 families.insert(family);
456 } 456 }
457 XftPatternDestroy(pattern); 457 XftPatternDestroy(pattern);
458 FcObjectSetDestroy(objectset); 458 FcObjectSetDestroy(objectset);
459 459
460 /* Copy the sorted list into the array */ 460 /* Copy the sorted list into the array */
461 FontNames.clear(); 461 FontNames.clear();
462 for (std::set<core::stringw>::iterator i = families.begin(); i != families.end(); i++) 462 for (std::set<core::stringw>::iterator i = families.begin(); i != families.end(); i++)
463 FontNames.push_back((*i).c_str()); 463 FontNames.push_back((*i).c_str());
464 } 464 }
465 465
466 bool CFontTool::makeBitmapFont(u32 fontIndex, u32 charsetIndex, s32 fontSize, u32 textureWidth, u32 textureHeight, bool bold, bool italic, bool aa, bool alpha) 466 bool CFontTool::makeBitmapFont(u32 fontIndex, u32 charsetIndex, s32 fontSize, u32 textureWidth, u32 textureHeight, bool bold, bool italic, bool aa, bool alpha)
467 { 467 {
468 if (fontIndex >= FontNames.size() || charsetIndex >= CharSets.size() ) 468 if (fontIndex >= FontNames.size() || charsetIndex >= CharSets.size() )
469 return false; 469 return false;
470 470
471 Display *display = (Display*) Device->getVideoDriver()->getExposedVideoData().OpenGLLinux.X11Display; 471 Display *display = (Display*) Device->getVideoDriver()->getExposedVideoData().OpenGLLinux.X11Display;
472 u32 screen = DefaultScreen(display); 472 u32 screen = DefaultScreen(display);
473 Window win = RootWindow(display, screen); 473 Window win = RootWindow(display, screen);
474 Visual *visual = DefaultVisual(display, screen); 474 Visual *visual = DefaultVisual(display, screen);
475 UseAlphaChannel = alpha; 475 UseAlphaChannel = alpha;
476 u32 currentImage = 0; 476 u32 currentImage = 0;
477 477
478 XftResult result; 478 XftResult result;
479 XftPattern *request = XftPatternCreate(); 479 XftPattern *request = XftPatternCreate();
480 char foundry[256], family[256]; 480 char foundry[256], family[256];
481 sprintf(&foundry[0],"%ls",CharSets[charsetIndex].c_str()); 481 sprintf(&foundry[0],"%ls",CharSets[charsetIndex].c_str());
482 sprintf(&family[0],"%ls",FontNames[fontIndex].c_str()); 482 sprintf(&family[0],"%ls",FontNames[fontIndex].c_str());
483 XftPatternAddString(request, XFT_FOUNDRY, &foundry[0]); 483 XftPatternAddString(request, XFT_FOUNDRY, &foundry[0]);
484 XftPatternAddString(request, XFT_FAMILY, &family[0]); 484 XftPatternAddString(request, XFT_FAMILY, &family[0]);
485 XftPatternAddInteger(request, XFT_PIXEL_SIZE, fontSize); 485 XftPatternAddInteger(request, XFT_PIXEL_SIZE, fontSize);
486 XftPatternAddInteger(request, XFT_WEIGHT, bold ? XFT_WEIGHT_BLACK : XFT_WEIGHT_LIGHT); 486 XftPatternAddInteger(request, XFT_WEIGHT, bold ? XFT_WEIGHT_BLACK : XFT_WEIGHT_LIGHT);
487 XftPatternAddInteger(request, XFT_SLANT, italic ? XFT_SLANT_ITALIC : XFT_SLANT_ROMAN); 487 XftPatternAddInteger(request, XFT_SLANT, italic ? XFT_SLANT_ITALIC : XFT_SLANT_ROMAN);
488 XftPatternAddBool(request, XFT_ANTIALIAS, aa); 488 XftPatternAddBool(request, XFT_ANTIALIAS, aa);
489 489
490 /* Find the closest font that matches the user choices and open it and check if the returned 490 /* Find the closest font that matches the user choices and open it and check if the returned
491 font has anti aliasing enabled by default, even if it wasn't requested */ 491 font has anti aliasing enabled by default, even if it wasn't requested */
492 FcBool aaEnabled; 492 FcBool aaEnabled;
493 XftPattern *found = XftFontMatch(display, DefaultScreen(display), request, &result); 493 XftPattern *found = XftFontMatch(display, DefaultScreen(display), request, &result);
494 XftPatternGetBool(found, XFT_ANTIALIAS, 0, &aaEnabled); 494 XftPatternGetBool(found, XFT_ANTIALIAS, 0, &aaEnabled);
495 aa = aaEnabled; 495 aa = aaEnabled;
496 XftFont *font = XftFontOpenPattern(display, found); 496 XftFont *font = XftFontOpenPattern(display, found);
497 497
498 // get rid of the current textures/images 498 // get rid of the current textures/images
499 for (u32 i=0; i<currentTextures.size(); ++i) 499 for (u32 i=0; i<currentTextures.size(); ++i)
500 currentTextures[i]->drop(); 500 currentTextures[i]->drop();
501 currentTextures.clear(); 501 currentTextures.clear();
502 for (u32 i=0; i<currentImages.size(); ++i) 502 for (u32 i=0; i<currentImages.size(); ++i)
503 currentImages[i]->drop(); 503 currentImages[i]->drop();
504 currentImages.clear(); 504 currentImages.clear();
505 CharMap.clear(); 505 CharMap.clear();
506 Areas.clear(); 506 Areas.clear();
507 507
508 /* Calculate the max height of the font. Annoyingly, it seems that the height property of the font 508 /* Calculate the max height of the font. Annoyingly, it seems that the height property of the font
509 is the maximum height of any single character, but a string of characters, aligned along their 509 is the maximum height of any single character, but a string of characters, aligned along their
510 baselines, can exceed this figure. Because I don't know any better way of doing it, I'm going to 510 baselines, can exceed this figure. Because I don't know any better way of doing it, I'm going to
511 have to use the brute force method. 511 have to use the brute force method.
512 512
513 Note: There will be a certain number of charters in a font, however they may not be grouped 513 Note: There will be a certain number of charters in a font, however they may not be grouped
514 consecutively, and could in fact be spread out with many gaps */ 514 consecutively, and could in fact be spread out with many gaps */
515 u32 maxY = 0; 515 u32 maxY = 0;
516 u32 charsFound = 0; 516 u32 charsFound = 0;
517 for (FT_UInt charCode = 0; charsFound < FcCharSetCount(font->charset); charCode++) 517 for (FT_UInt charCode = 0; charsFound < FcCharSetCount(font->charset); charCode++)
518 { 518 {
519 if (!XftCharExists(display, font, charCode)) 519 if (!XftCharExists(display, font, charCode))
520 continue; 520 continue;
521 521
522 charsFound++; 522 charsFound++;
523 523
524 XGlyphInfo extents; 524 XGlyphInfo extents;
525 XftTextExtents32(display, font, &charCode, 1, &extents); 525 XftTextExtents32(display, font, &charCode, 1, &extents);
526 if ((extents.xOff <= 0) && (extents.height <= 0)) 526 if ((extents.xOff <= 0) && (extents.height <= 0))
527 continue; 527 continue;
528 528
529 /* Calculate the width and height, adding 1 extra pixel if anti aliasing is enabled */ 529 /* Calculate the width and height, adding 1 extra pixel if anti aliasing is enabled */
530 u32 chWidth = extents.xOff + (aa ? 1 : 0); 530 u32 chWidth = extents.xOff + (aa ? 1 : 0);
531 u32 chHeight = (font->ascent - extents.y + extents.height) + (aa ? 1 : 0); 531 u32 chHeight = (font->ascent - extents.y + extents.height) + (aa ? 1 : 0);
532 if (chHeight > maxY) 532 if (chHeight > maxY)
533 maxY = chHeight; 533 maxY = chHeight;
534 534
535 /* Store the character details here */ 535 /* Store the character details here */
536 SFontArea fontArea; 536 SFontArea fontArea;
537 fontArea.rectangle = core::rect<s32>(0, 0, chWidth, chHeight); 537 fontArea.rectangle = core::rect<s32>(0, 0, chWidth, chHeight);
538 CharMap.insert(charCode, Areas.size()); 538 CharMap.insert(charCode, Areas.size());
539 Areas.push_back(fontArea); 539 Areas.push_back(fontArea);
540 } 540 }
541 core::stringc logmsg = "Found "; 541 core::stringc logmsg = "Found ";
542 logmsg += (s32) (CharMap.size() + 1); 542 logmsg += (s32) (CharMap.size() + 1);
543 logmsg += " characters"; 543 logmsg += " characters";
544 Device->getLogger()->log(logmsg.c_str()); 544 Device->getLogger()->log(logmsg.c_str());
545 545
546 /* Get the size of the chars and allocate them a position on a texture. If the next character that 546 /* Get the size of the chars and allocate them a position on a texture. If the next character that
547 is added would be outside the width or height of the texture, then a new texture is added */ 547 is added would be outside the width or height of the texture, then a new texture is added */
548 u32 currentX = 0, currentY = 0, rowY = 0; 548 u32 currentX = 0, currentY = 0, rowY = 0;
549 for (core::map<wchar_t, u32>::Iterator it = CharMap.getIterator(); !it.atEnd(); it++) 549 for (core::map<wchar_t, u32>::Iterator it = CharMap.getIterator(); !it.atEnd(); it++)
550 { 550 {
551 s32 currentArea = (*it).getValue(); 551 s32 currentArea = (*it).getValue();
552 SFontArea *fontArea = &Areas[currentArea]; 552 SFontArea *fontArea = &Areas[currentArea];
553 u32 chWidth = fontArea->rectangle.LowerRightCorner.X; 553 u32 chWidth = fontArea->rectangle.LowerRightCorner.X;
554 u32 chHeight = fontArea->rectangle.LowerRightCorner.Y; 554 u32 chHeight = fontArea->rectangle.LowerRightCorner.Y;
555 555
556 /* If the width of this char will exceed the textureWidth then start a new row */ 556 /* If the width of this char will exceed the textureWidth then start a new row */
557 if ((currentX + chWidth) > textureWidth) 557 if ((currentX + chWidth) > textureWidth)
558 { 558 {
559 currentY += rowY; 559 currentY += rowY;
560 currentX = 0; 560 currentX = 0;
561 561
562 /* If the new row added to the texture exceeds the textureHeight then start a new texture */ 562 /* If the new row added to the texture exceeds the textureHeight then start a new texture */
563 if ((currentY + rowY) > textureHeight) 563 if ((currentY + rowY) > textureHeight)
564 { 564 {
565 currentImage++; 565 currentImage++;
566 currentY = 0; 566 currentY = 0;
567 } 567 }
568 rowY = 0; 568 rowY = 0;
569 } 569 }
570 570
571 /* Update the area with the current x and y and texture */ 571 /* Update the area with the current x and y and texture */
572 fontArea->rectangle = core::rect<s32>(currentX, currentY, currentX + chWidth, currentY + chHeight); 572 fontArea->rectangle = core::rect<s32>(currentX, currentY, currentX + chWidth, currentY + chHeight);
573 fontArea->sourceimage = currentImage; 573 fontArea->sourceimage = currentImage;
574 currentX += chWidth + 1; 574 currentX += chWidth + 1;
575 if (chHeight + 1 > rowY) 575 if (chHeight + 1 > rowY)
576 rowY = chHeight + 1; 576 rowY = chHeight + 1;
577 } 577 }
578 578
579 /* The last row of chars and the last texture weren't accounted for in the loop, so add them here */ 579 /* The last row of chars and the last texture weren't accounted for in the loop, so add them here */
580 currentY += rowY; 580 currentY += rowY;
581 u32 lastTextureHeight = getTextureSizeFromSurfaceSize(currentY); 581 u32 lastTextureHeight = getTextureSizeFromSurfaceSize(currentY);
582 currentImages.set_used(currentImage + 1); 582 currentImages.set_used(currentImage + 1);
583 currentTextures.set_used(currentImage + 1); 583 currentTextures.set_used(currentImage + 1);
584 584
585 /* Initialise colours */ 585 /* Initialise colours */
586 XftColor colFore, colBack; 586 XftColor colFore, colBack;
587 XRenderColor xFore = {0xffff, 0xffff, 0xffff, 0xffff}; 587 XRenderColor xFore = {0xffff, 0xffff, 0xffff, 0xffff};
588 XRenderColor xBack = {0x0000, 0x0000, 0x0000, 0xffff}; 588 XRenderColor xBack = {0x0000, 0x0000, 0x0000, 0xffff};
589 XftColorAllocValue(display, DefaultVisual(display, screen), DefaultColormap(display, screen), &xFore, &colFore); 589 XftColorAllocValue(display, DefaultVisual(display, screen), DefaultColormap(display, screen), &xFore, &colFore);
590 XftColorAllocValue(display, DefaultVisual(display, screen), DefaultColormap(display, screen), &xBack, &colBack); 590 XftColorAllocValue(display, DefaultVisual(display, screen), DefaultColormap(display, screen), &xBack, &colBack);
591 591
592 /* Create a pixmap that is large enough to hold any character in the font */ 592 /* Create a pixmap that is large enough to hold any character in the font */
593 Pixmap pixmap = XCreatePixmap(display, win, textureWidth, maxY, DefaultDepth(display, screen)); 593 Pixmap pixmap = XCreatePixmap(display, win, textureWidth, maxY, DefaultDepth(display, screen));
594 XftDraw *draw = XftDrawCreate(display, pixmap, visual, DefaultColormap(display, screen)); 594 XftDraw *draw = XftDrawCreate(display, pixmap, visual, DefaultColormap(display, screen));
595 595
596 /* Render the chars */ 596 /* Render the chars */
597 for (currentImage = 0; currentImage < currentImages.size(); ++currentImage) 597 for (currentImage = 0; currentImage < currentImages.size(); ++currentImage)
598 { 598 {
599 core::stringc logmsg = "Creating image "; 599 core::stringc logmsg = "Creating image ";
600 logmsg += (s32) (currentImage+1); 600 logmsg += (s32) (currentImage+1);
601 logmsg += " of "; 601 logmsg += " of ";
602 logmsg += (s32) currentImages.size(); 602 logmsg += (s32) currentImages.size();
603 Device->getLogger()->log(logmsg.c_str()); 603 Device->getLogger()->log(logmsg.c_str());
604 604
605 /* The last texture that is saved is vertically shrunk to fit the characters drawn on it */ 605 /* The last texture that is saved is vertically shrunk to fit the characters drawn on it */
606 u32 texHeight = textureHeight; 606 u32 texHeight = textureHeight;
607 if (currentImage == currentImages.size() - 1) 607 if (currentImage == currentImages.size() - 1)
608 texHeight = lastTextureHeight; 608 texHeight = lastTextureHeight;
609 609
610 /* The texture that holds this "page" of characters */ 610 /* The texture that holds this "page" of characters */
611 currentImages[currentImage] = Device->getVideoDriver()->createImage(video::ECF_A8R8G8B8, core::dimension2du(textureWidth, texHeight)); 611 currentImages[currentImage] = Device->getVideoDriver()->createImage(video::ECF_A8R8G8B8, core::dimension2du(textureWidth, texHeight));
612 currentImages[currentImage]->fill(video::SColor(alpha ? 0 : 255,0,0,0)); 612 currentImages[currentImage]->fill(video::SColor(alpha ? 0 : 255,0,0,0));
613 613
614 for (core::map<wchar_t, u32>::Iterator it = CharMap.getIterator(); !it.atEnd(); it++) 614 for (core::map<wchar_t, u32>::Iterator it = CharMap.getIterator(); !it.atEnd(); it++)
615 { 615 {
616 FcChar32 wch = (*it).getKey(); 616 FcChar32 wch = (*it).getKey();
617 s32 currentArea = (*it).getValue(); 617 s32 currentArea = (*it).getValue();
618 if (Areas[currentArea].sourceimage == currentImage) 618 if (Areas[currentArea].sourceimage == currentImage)
619 { 619 {
620 SFontArea *fontArea = &Areas[currentArea]; 620 SFontArea *fontArea = &Areas[currentArea];
621 u32 chWidth = fontArea->rectangle.LowerRightCorner.X - fontArea->rectangle.UpperLeftCorner.X; 621 u32 chWidth = fontArea->rectangle.LowerRightCorner.X - fontArea->rectangle.UpperLeftCorner.X;
622 u32 chHeight = fontArea->rectangle.LowerRightCorner.Y - fontArea->rectangle.UpperLeftCorner.Y; 622 u32 chHeight = fontArea->rectangle.LowerRightCorner.Y - fontArea->rectangle.UpperLeftCorner.Y;
623 623
624 /* Draw the glyph onto the pixmap */ 624 /* Draw the glyph onto the pixmap */
625 XGlyphInfo extents; 625 XGlyphInfo extents;
626 XftDrawRect(draw, &colBack, 0, 0, chWidth, chHeight); 626 XftDrawRect(draw, &colBack, 0, 0, chWidth, chHeight);
627 XftTextExtents32(display, font, &wch, 1, &extents); 627 XftTextExtents32(display, font, &wch, 1, &extents);
628 XftDrawString32(draw, &colFore, font, extents.x, extents.y, &wch, 1); 628 XftDrawString32(draw, &colFore, font, extents.x, extents.y, &wch, 1);
629 629
630 /* Convert the pixmap into an image, then copy it onto the Irrlicht texture, pixel by pixel. 630 /* Convert the pixmap into an image, then copy it onto the Irrlicht texture, pixel by pixel.
631 There's bound to be a faster way, but this is adequate */ 631 There's bound to be a faster way, but this is adequate */
632 u32 xDest = fontArea->rectangle.UpperLeftCorner.X; 632 u32 xDest = fontArea->rectangle.UpperLeftCorner.X;
633 u32 yDest = fontArea->rectangle.UpperLeftCorner.Y + font->ascent - extents.y; 633 u32 yDest = fontArea->rectangle.UpperLeftCorner.Y + font->ascent - extents.y;
634 XImage *image = XGetImage(display, pixmap, 0, 0, chWidth, chHeight, 0xffffff, XYPixmap); 634 XImage *image = XGetImage(display, pixmap, 0, 0, chWidth, chHeight, 0xffffff, XYPixmap);
635 if (image) 635 if (image)
636 { 636 {
637 for (u32 ySrc = 0; ySrc < chHeight; ySrc++) 637 for (u32 ySrc = 0; ySrc < chHeight; ySrc++)
638 for (u32 xSrc = 0; xSrc < chWidth; xSrc++) 638 for (u32 xSrc = 0; xSrc < chWidth; xSrc++)
639 { 639 {
640 /* Get the pixel colour and break it down into rgb components */ 640 /* Get the pixel colour and break it down into rgb components */
641 u32 col = XGetPixel(image, xSrc, ySrc); 641 u32 col = XGetPixel(image, xSrc, ySrc);
642 u32 a = 255; 642 u32 a = 255;
643 u32 r = col & visual->red_mask; 643 u32 r = col & visual->red_mask;
644 u32 g = col & visual->green_mask; 644 u32 g = col & visual->green_mask;
645 u32 b = col & visual->blue_mask; 645 u32 b = col & visual->blue_mask;
646 while (r > 0xff) r >>= 8; 646 while (r > 0xff) r >>= 8;
647 while (g > 0xff) g >>= 8; 647 while (g > 0xff) g >>= 8;
648 while (b > 0xff) b >>= 8; 648 while (b > 0xff) b >>= 8;
649 649
650 /* To make the background transparent, set the colour to 100% white and the alpha to 650 /* To make the background transparent, set the colour to 100% white and the alpha to
651 the average of the three rgb colour components to maintain the anti-aliasing */ 651 the average of the three rgb colour components to maintain the anti-aliasing */
652 if (alpha) 652 if (alpha)
653 { 653 {
654 a = (r + g + b) / 3; 654 a = (r + g + b) / 3;
655 r = 255; 655 r = 255;
656 g = 255; 656 g = 255;
657 b = 255; 657 b = 255;
658 } 658 }
659 currentImages[currentImage]->setPixel(xDest + xSrc,yDest + ySrc,video::SColor(a,r,g,b)); 659 currentImages[currentImage]->setPixel(xDest + xSrc,yDest + ySrc,video::SColor(a,r,g,b));
660 } 660 }
661 image->f.destroy_image(image); 661 image->f.destroy_image(image);
662 } 662 }
663 } 663 }
664 } 664 }
665 665
666 /* Add the texture to the list */ 666 /* Add the texture to the list */
667 currentTextures[currentImage] = Device->getVideoDriver()->addTexture("GUIFontImage",currentImages[currentImage]); 667 currentTextures[currentImage] = Device->getVideoDriver()->addTexture("GUIFontImage",currentImages[currentImage]);
668 currentTextures[currentImage]->grab(); 668 currentTextures[currentImage]->grab();
669 } 669 }
670 670
671 XftColorFree (display, visual, DefaultColormap(display, screen), &colFore); 671 XftColorFree (display, visual, DefaultColormap(display, screen), &colFore);
672 XftColorFree (display, visual, DefaultColormap(display, screen), &colBack); 672 XftColorFree (display, visual, DefaultColormap(display, screen), &colBack);
673 XftFontClose(display,font); 673 XftFontClose(display,font);
674 XftPatternDestroy(request); 674 XftPatternDestroy(request);
675 XftDrawDestroy(draw); 675 XftDrawDestroy(draw);
676 XFreePixmap(display, pixmap); 676 XFreePixmap(display, pixmap);
677 return true; 677 return true;
678 } 678 }
679#endif 679#endif
680 680
681 CFontTool::~CFontTool() 681 CFontTool::~CFontTool()
682 { 682 {
683#ifdef _IRR_WINDOWS_ 683#ifdef _IRR_WINDOWS_
684 // destroy display context 684 // destroy display context
685 if (dc) 685 if (dc)
686 DeleteDC(dc); 686 DeleteDC(dc);
687#endif 687#endif
688 688
689 // drop textures+images 689 // drop textures+images
690 for (u32 i=0; i<currentTextures.size(); ++i) 690 for (u32 i=0; i<currentTextures.size(); ++i)
691 currentTextures[i]->drop(); 691 currentTextures[i]->drop();
692 currentTextures.clear(); 692 currentTextures.clear();
693 693
694 for (u32 i=0; i<currentImages.size(); ++i) 694 for (u32 i=0; i<currentImages.size(); ++i)
695 currentImages[i]->drop(); 695 currentImages[i]->drop();
696 currentImages.clear(); 696 currentImages.clear();
697 } 697 }
698 698
699bool CFontTool::saveBitmapFont(const c8 *filename, const c8* format) 699bool CFontTool::saveBitmapFont(const c8 *filename, const c8* format)
700{ 700{
701 if (currentImages.size() == 0) 701 if (currentImages.size() == 0)
702 { 702 {
703 Device->getLogger()->log("No image data to write, aborting."); 703 Device->getLogger()->log("No image data to write, aborting.");
704 return false; 704 return false;
705 } 705 }
706 706
707 core::stringc fn = filename; 707 core::stringc fn = filename;
708 core::stringc imagename = filename; 708 core::stringc imagename = filename;
709 fn += ".xml"; 709 fn += ".xml";
710 710
711 io::IXMLWriter *writer = Device->getFileSystem()->createXMLWriter(fn.c_str()); 711 io::IXMLWriter *writer = Device->getFileSystem()->createXMLWriter(fn.c_str());
712 712
713 // header and line breaks 713 // header and line breaks
714 writer->writeXMLHeader(); 714 writer->writeXMLHeader();
715 writer->writeLineBreak(); 715 writer->writeLineBreak();
716 716
717 // write information 717 // write information
718 writer->writeElement(L"font", false, L"type", L"bitmap"); 718 writer->writeElement(L"font", false, L"type", L"bitmap");
719 writer->writeLineBreak(); 719 writer->writeLineBreak();
720 writer->writeLineBreak(); 720 writer->writeLineBreak();
721 721
722 // write images and link to them 722 // write images and link to them
723 for (u32 i=0; i<currentImages.size(); ++i) 723 for (u32 i=0; i<currentImages.size(); ++i)
724 { 724 {
725 imagename = filename; 725 imagename = filename;
726 imagename += (s32)i; 726 imagename += (s32)i;
727 imagename += "."; 727 imagename += ".";
728 imagename += format; 728 imagename += format;
729 Device->getVideoDriver()->writeImageToFile(currentImages[i],imagename.c_str()); 729 Device->getVideoDriver()->writeImageToFile(currentImages[i],imagename.c_str());
730 730
731 writer->writeElement(L"Texture", true, 731 writer->writeElement(L"Texture", true,
732 L"index", core::stringw(i).c_str(), 732 L"index", core::stringw(i).c_str(),
733 L"filename", core::stringw(imagename.c_str()).c_str(), 733 L"filename", core::stringw(imagename.c_str()).c_str(),
734 L"hasAlpha", UseAlphaChannel ? L"true" : L"false"); 734 L"hasAlpha", UseAlphaChannel ? L"true" : L"false");
735 writer->writeLineBreak(); 735 writer->writeLineBreak();
736 } 736 }
737 737
738 writer->writeLineBreak(); 738 writer->writeLineBreak();
739 739
740 // write each character 740 // write each character
741 core::map<wchar_t, u32>::Iterator it = CharMap.getIterator(); 741 core::map<wchar_t, u32>::Iterator it = CharMap.getIterator();
742 while (!it.atEnd()) 742 while (!it.atEnd())
743 { 743 {
744 SFontArea &fa = Areas[(*it).getValue()]; 744 SFontArea &fa = Areas[(*it).getValue()];
745 745
746 wchar_t c[2]; 746 wchar_t c[2];
747 c[0] = (*it).getKey(); 747 c[0] = (*it).getKey();
748 c[1] = L'\0'; 748 c[1] = L'\0';
749 core::stringw area, under, over, image; 749 core::stringw area, under, over, image;
750 area = core::stringw(fa.rectangle.UpperLeftCorner.X); 750 area = core::stringw(fa.rectangle.UpperLeftCorner.X);
751 area += L", "; 751 area += L", ";
752 area += fa.rectangle.UpperLeftCorner.Y; 752 area += fa.rectangle.UpperLeftCorner.Y;
753 area += L", "; 753 area += L", ";
754 area += fa.rectangle.LowerRightCorner.X; 754 area += fa.rectangle.LowerRightCorner.X;
755 area += L", "; 755 area += L", ";
756 area += fa.rectangle.LowerRightCorner.Y; 756 area += fa.rectangle.LowerRightCorner.Y;
757 757
758 core::array<core::stringw> names; 758 core::array<core::stringw> names;
759 core::array<core::stringw> values; 759 core::array<core::stringw> values;
760 names.clear(); 760 names.clear();
761 values.clear(); 761 values.clear();
762 // char 762 // char
763 names.push_back(core::stringw(L"c")); 763 names.push_back(core::stringw(L"c"));
764 values.push_back(core::stringw(c)); 764 values.push_back(core::stringw(c));
765 // image number 765 // image number
766 if (fa.sourceimage != 0) 766 if (fa.sourceimage != 0)
767 { 767 {
768 image = core::stringw(fa.sourceimage); 768 image = core::stringw(fa.sourceimage);
769 names.push_back(core::stringw(L"i")); 769 names.push_back(core::stringw(L"i"));
770 values.push_back(image); 770 values.push_back(image);
771 } 771 }
772 // rectangle 772 // rectangle
773 names.push_back(core::stringw(L"r")); 773 names.push_back(core::stringw(L"r"));
774 values.push_back(area); 774 values.push_back(area);
775 775
776 if (fa.underhang != 0) 776 if (fa.underhang != 0)
777 { 777 {
778 under = core::stringw(fa.underhang); 778 under = core::stringw(fa.underhang);
779 names.push_back(core::stringw(L"u")); 779 names.push_back(core::stringw(L"u"));
780 values.push_back(under); 780 values.push_back(under);
781 } 781 }
782 if (fa.overhang != 0) 782 if (fa.overhang != 0)
783 { 783 {
784 over = core::stringw(fa.overhang); 784 over = core::stringw(fa.overhang);
785 names.push_back(core::stringw(L"o")); 785 names.push_back(core::stringw(L"o"));
786 values.push_back(over); 786 values.push_back(over);
787 } 787 }
788 writer->writeElement(L"c", true, names, values); 788 writer->writeElement(L"c", true, names, values);
789 789
790 writer->writeLineBreak(); 790 writer->writeLineBreak();
791 it++; 791 it++;
792 } 792 }
793 793
794 writer->writeClosingTag(L"font"); 794 writer->writeClosingTag(L"font");
795 795
796 writer->drop(); 796 writer->drop();
797 797
798 Device->getLogger()->log("Bitmap font saved."); 798 Device->getLogger()->log("Bitmap font saved.");
799 799
800 return true; 800 return true;
801} 801}