Fixed a stupid bug when exporting meshes with empty material slots.
[blender.git] / intern / bmfont / intern / BMF_BitmapFont.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  */
31
32 /**
33
34  * $Id$
35  * Copyright (C) 2001 NaN Technologies B.V.
36  */
37
38 #include <string.h>
39
40 #ifdef HAVE_CONFIG_H
41 #include <config.h>
42 #endif
43
44 #if defined(WIN32) || defined(__APPLE__)
45         #ifdef WIN32
46         #if !defined(__CYGWIN32__)
47         #pragma warning(disable:4244)
48         #endif /* __CYGWIN32__ */
49                 #include <windows.h>
50                 #include <GL/gl.h>
51         #else // WIN32
52                 // __APPLE__ is defined
53                 #include <AGL/gl.h>
54         #endif // WIN32
55 #else // defined(WIN32) || defined(__APPLE__)
56         #include <GL/gl.h>
57 #endif // defined(WIN32) || defined(__APPLE__)
58
59 #include "BMF_BitmapFont.h"
60
61
62 #ifdef __APPLE__         
63 #include <stdio.h>
64
65 static int needs_nvidia_rasterpos_workaround(void)
66 {
67         static int well_is_it= -1;
68         
69         if (well_is_it==-1)
70         {
71                 well_is_it= (strncmp((char *)glGetString(GL_RENDERER), "NVIDIA GeForce 6800", 18) == 0);
72                 if ( well_is_it != 0)
73                 {
74                         const GLubyte* vers = glGetString(GL_VERSION);
75                         const GLubyte* v = vers;
76                         int major = 0, minor = 0, sub = 0;
77                         
78                         //advance to the '-'
79                         while ((*v != 0) && (*v!='-'))
80                                 v++;
81                         
82                         if (*v == '-')
83                         {
84                                 int i = 0;
85                                 v++;
86                                 
87                                 while ((v[i] <= '9') && (v[i] >= '0'))
88                                 {
89                                         major *=10;
90                                         major += v[i]-'0';
91                                         i++;
92                                 }
93                                 
94                                 if (v[i] == '.')
95                                 {
96                                         i++;
97                                         while ((v[i] <= '9') && (v[i] >= '0'))
98                                         {
99                                                 minor *=10;
100                                                 minor += v[i]-'0';
101                                                 i++;
102                                         }
103                                 }
104                                 else
105                                         major = -1;
106                                 
107                                 if (v[i] == '.')
108                                 {
109                                         i++;
110                                         while ((v[i] <= '9') && (v[i] >= '0'))
111                                         {
112                                                 sub *=10;
113                                                 sub += v[i]-'0';
114                                                 i++;
115                                         }
116                                 }
117                                 else
118                                         minor = -1;
119                         }
120
121                         //OS X 10.4.3 is the first version that contained the fix for this problem
122                         // and the 6800's driver version in it is 1.4.16.  So anything after that
123                         // doesn't need the workaround
124
125                         if ( (major == -1) || (minor == -1))
126                         //If anything went wrong don't do the workaround
127                         //
128                                 well_is_it = 0;
129                         else if ( (major <= 1) && (minor <= 4) && (sub < 16))
130                                 well_is_it = 1;
131                         else
132                                 well_is_it = 0;
133                 }       
134         }
135
136         return well_is_it;
137 }
138
139
140 #endif
141
142 BMF_BitmapFont::BMF_BitmapFont(BMF_FontData* fontData)
143 : m_fontData(fontData)
144 {
145 }
146
147
148 BMF_BitmapFont::~BMF_BitmapFont(void)
149 {
150 }
151
152 void BMF_BitmapFont::DrawString(char* str)
153 {
154         GLint alignment;
155         unsigned char c;
156
157 #ifdef __APPLE__         
158      GLint vp[4];  // hack stuff         
159      GLubyte nullm = 0;      // hack stuff       
160          
161      if(needs_nvidia_rasterpos_workaround()) {   // was is_a_really_crappy_nvidia_card()
162              glGetIntegerv(GL_VIEWPORT, vp);   // hack stuff     
163          
164              glBitmap(1, 1, 0, 0, -vp[0], vp[1], &nullm);        
165          
166          }       
167  #endif
168  
169         glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
170         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
171         
172         while ( (c = (unsigned char) *str++) ) {
173                 BMF_CharData & cd = m_fontData->chars[c];
174                 
175                 if (cd.data_offset==-1) {
176                         GLubyte nullBitmap = 0;
177                 
178                         glBitmap(1, 1, 0, 0, cd.advance, 0, &nullBitmap);       
179                 } else {
180                         GLubyte *bitmap = &m_fontData->bitmap_data[cd.data_offset];
181                 
182                         glBitmap(cd.width, cd.height, cd.xorig, cd.yorig, cd.advance, 0, bitmap);
183                 }
184         }
185
186         glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
187 }
188
189
190 int BMF_BitmapFont::GetStringWidth(char* str)
191 {
192         unsigned char c;
193         int length = 0;
194
195         while ( (c = (unsigned char) *str++) ) {
196                 length += m_fontData->chars[c].advance;
197         }
198         
199         return length;
200 }
201
202 void BMF_BitmapFont::GetBoundingBox(int & xMin, int & yMin, int & xMax, int & yMax)
203 {
204         xMin = m_fontData->xmin;
205         yMin = m_fontData->ymin;
206         xMax = m_fontData->xmax;
207         yMax = m_fontData->ymax;
208 }
209
210 int BMF_BitmapFont::GetTexture()
211 {
212         int fWidth = m_fontData->xmax - m_fontData->xmin;
213         int fHeight = m_fontData->ymax - m_fontData->ymin;
214         
215         if (fWidth>=16 || fHeight>=16) {
216                 return -1;
217         }
218         
219         int cRows = 16, cCols = 16;
220         int cWidth = 16, cHeight = 16;
221         int iWidth = cCols*cWidth;
222         int iHeight = cRows*cHeight;
223         GLubyte *img = new GLubyte [iHeight*iWidth];
224         GLuint texId;
225
226         int baseLine = -(m_fontData->ymin);
227         
228         memset(img, 0, iHeight*iWidth);
229         for (int i = 0; i<256; i++) {
230                 BMF_CharData & cd = m_fontData->chars[i];
231                 
232                 if (cd.data_offset != -1) {
233                         int cellX = i%16;
234                         int cellY = i/16;
235                         
236                         for (int y = 0; y<cd.height; y++) {
237                                 GLubyte* imgRow = &img[(cellY*cHeight + y + baseLine - cd.yorig)*iWidth];
238                                 GLubyte* chrRow = &m_fontData->bitmap_data[cd.data_offset + ((cd.width+7)/8)*y];
239
240                                 for (int x = 0; x<cd.width; x++) {
241                                         GLubyte* imgPxl = &imgRow[(cellX*cWidth + x - cd.xorig)];
242                                         int byteIdx = x/8;
243                                         int bitIdx = 7 - (x%8);
244                                         
245                                         if (chrRow[byteIdx]&(1<<bitIdx)) {
246                                                 imgPxl[0] = 255;
247                                         }
248                                 }
249                         }
250                 }
251         }
252         
253         glGenTextures(1, &texId);
254         
255         glBindTexture(GL_TEXTURE_2D, texId);
256
257         glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA4, iWidth, iHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, img);
258         if (glGetError()) {
259                 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE4_ALPHA4, iWidth, iHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, img);
260         }
261         
262         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
263         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
264         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
265         
266         delete [] img;
267         
268         return texId;
269 }
270
271 void BMF_BitmapFont::DrawStringTexture(char *str, float x, float y, float z)
272 {
273         unsigned char c;
274         float pos = 0;
275         
276         int baseLine = -(m_fontData->ymin);
277
278         glBegin(GL_QUADS);
279         while ( (c = (unsigned char) *str++) ) {
280                 BMF_CharData & cd = m_fontData->chars[c];
281                 
282                 if (cd.data_offset != -1) {
283                         float cellX = (c%16)/16.0;
284                         float cellY = (c/16)/16.0;
285                 
286                         glTexCoord2f(cellX + 1.0/16.0, cellY);
287                         glVertex3f(x + pos + 16.0, -baseLine + y + 0.0, z);
288
289                         glTexCoord2f(cellX + 1.0/16.0, cellY + 1.0/16.0);
290                         glVertex3f(x + pos + 16.0, -baseLine + y + 16.0, z);
291
292                         glTexCoord2f(cellX, cellY + 1.0/16.0);
293                         glVertex3f(x + pos + 0.0, -baseLine + y + 16.0, z);
294
295                         glTexCoord2f(cellX, cellY);
296                         glVertex3f(x + pos + 0.0, -baseLine + y + 0.0, z);
297                 }
298                 
299                 pos += cd.advance;
300         }
301         glEnd();
302 }