render stamp drawing is now done everywhere - (not just when saving
[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
39 #include <stdio.h>
40
41
42
43 #include <string.h>
44
45 #ifdef HAVE_CONFIG_H
46 #include <config.h>
47 #endif
48
49 #if defined(WIN32) || defined(__APPLE__)
50         #ifdef WIN32
51         #if !defined(__CYGWIN32__)
52         #pragma warning(disable:4244)
53         #endif /* __CYGWIN32__ */
54                 #include <windows.h>
55                 #include <GL/gl.h>
56         #else // WIN32
57                 // __APPLE__ is defined
58                 #include <AGL/gl.h>
59         #endif // WIN32
60 #else // defined(WIN32) || defined(__APPLE__)
61         #include <GL/gl.h>
62 #endif // defined(WIN32) || defined(__APPLE__)
63
64 #include "BMF_BitmapFont.h"
65
66
67 BMF_BitmapFont::BMF_BitmapFont(BMF_FontData* fontData)
68 : m_fontData(fontData)
69 {
70 }
71
72
73 BMF_BitmapFont::~BMF_BitmapFont(void)
74 {
75 }
76
77 void BMF_BitmapFont::DrawString(char* str)
78 {
79         GLint alignment;
80         unsigned char c;
81
82         glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
83         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
84         
85         while ( (c = (unsigned char) *str++) ) {
86                 BMF_CharData & cd = m_fontData->chars[c];
87                 
88                 if (cd.data_offset==-1) {
89                         GLubyte nullBitmap = 0;
90                 
91                         glBitmap(1, 1, 0, 0, cd.advance, 0, &nullBitmap);       
92                 } else {
93                         GLubyte *bitmap = &m_fontData->bitmap_data[cd.data_offset];
94                 
95                         glBitmap(cd.width, cd.height, cd.xorig, cd.yorig, cd.advance, 0, bitmap);
96                 }
97         }
98
99         glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
100 }
101
102
103 int BMF_BitmapFont::GetStringWidth(char* str)
104 {
105         unsigned char c;
106         int length = 0;
107
108         while ( (c = (unsigned char) *str++) ) {
109                 length += m_fontData->chars[c].advance;
110         }
111         
112         return length;
113 }
114
115 void BMF_BitmapFont::GetFontBoundingBox(int & xMin, int & yMin, int & xMax, int & yMax)
116 {
117         xMin = m_fontData->xmin;
118         yMin = m_fontData->ymin;
119         xMax = m_fontData->xmax;
120         yMax = m_fontData->ymax;
121 }
122
123 int BMF_BitmapFont::GetFontHeight( void )
124 {
125         return m_fontData->ymax - m_fontData->ymin;
126 }
127
128 void BMF_BitmapFont::GetStringBoundingBox(char* str, float*llx, float *lly, float *urx, float *ury)
129 {
130         unsigned char c;
131         int length = 0;
132         int ascent = 0;
133         int descent = 0;
134
135         while ( (c = (unsigned char) *str++) ) {
136                 length += m_fontData->chars[c].advance;
137                 int d = m_fontData->chars[c].yorig;
138                 int a = m_fontData->chars[c].height - m_fontData->chars[c].yorig;
139                 if(a > ascent) ascent = a;
140                 if(d > descent) descent = d;
141         }
142         *llx = (float)0;
143         *lly = (float)-descent;
144         *urx = (float)length;
145         *ury = (float)ascent;
146 }
147
148
149 int BMF_BitmapFont::GetTexture()
150 {
151         int fWidth = m_fontData->xmax - m_fontData->xmin;
152         int fHeight = m_fontData->ymax - m_fontData->ymin;
153         
154         if (fWidth>=16 || fHeight>=16) {
155                 return -1;
156         }
157         
158         int cRows = 16, cCols = 16;
159         int cWidth = 16, cHeight = 16;
160         int iWidth = cCols*cWidth;
161         int iHeight = cRows*cHeight;
162         GLubyte *img = new GLubyte [iHeight*iWidth];
163         GLuint texId;
164
165         int baseLine = -(m_fontData->ymin);
166         
167         memset(img, 0, iHeight*iWidth);
168         for (int i = 0; i<256; i++) {
169                 BMF_CharData & cd = m_fontData->chars[i];
170                 
171                 if (cd.data_offset != -1) {
172                         int cellX = i%16;
173                         int cellY = i/16;
174                         
175                         for (int y = 0; y<cd.height; y++) {
176                                 GLubyte* imgRow = &img[(cellY*cHeight + y + baseLine - cd.yorig)*iWidth];
177                                 GLubyte* chrRow = &m_fontData->bitmap_data[cd.data_offset + ((cd.width+7)/8)*y];
178
179                                 for (int x = 0; x<cd.width; x++) {
180                                         GLubyte* imgPxl = &imgRow[(cellX*cWidth + x - cd.xorig)];
181                                         int byteIdx = x/8;
182                                         int bitIdx = 7 - (x%8);
183                                         
184                                         if (chrRow[byteIdx]&(1<<bitIdx)) {
185                                                 imgPxl[0] = 255;
186                                         }
187                                 }
188                         }
189                 }
190         }
191         
192         glGenTextures(1, &texId);
193         
194         glBindTexture(GL_TEXTURE_2D, texId);
195
196         glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA4, iWidth, iHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, img);
197         if (glGetError()) {
198                 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE4_ALPHA4, iWidth, iHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, img);
199         }
200         
201         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
202         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
203         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
204         
205         delete [] img;
206         
207         return texId;
208 }
209
210 void BMF_BitmapFont::DrawStringTexture(char *str, float x, float y, float z)
211 {
212         unsigned char c;
213         float pos = 0;
214         
215         int baseLine = -(m_fontData->ymin);
216
217         glBegin(GL_QUADS);
218         while ( (c = (unsigned char) *str++) ) {
219                 BMF_CharData & cd = m_fontData->chars[c];
220                 
221                 if (cd.data_offset != -1) {
222                         float cellX = (c%16)/16.0;
223                         float cellY = (c/16)/16.0;
224                 
225                         glTexCoord2f(cellX + 1.0/16.0, cellY);
226                         glVertex3f(x + pos + 16.0, -baseLine + y + 0.0, z);
227
228                         glTexCoord2f(cellX + 1.0/16.0, cellY + 1.0/16.0);
229                         glVertex3f(x + pos + 16.0, -baseLine + y + 16.0, z);
230
231                         glTexCoord2f(cellX, cellY + 1.0/16.0);
232                         glVertex3f(x + pos + 0.0, -baseLine + y + 16.0, z);
233
234                         glTexCoord2f(cellX, cellY);
235                         glVertex3f(x + pos + 0.0, -baseLine + y + 0.0, z);
236                 }
237                 
238                 pos += cd.advance;
239         }
240         glEnd();
241 }
242
243 #define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val))
244 void BMF_BitmapFont::DrawStringBuf(char *str, int posx, int posy, float *col, unsigned char *buf, float *fbuf, int w, int h)
245 {
246         int x, y;
247         
248         if (buf==0 && fbuf==0)
249                 return;
250
251         /*offset for font*/
252         posx -= m_fontData->xmin;
253         posy -= m_fontData->ymin;
254         
255         if (buf) {
256                 unsigned char colch[4];
257                 unsigned char *max, *pixel;
258                 unsigned char c;
259                 
260                 for (x=0; x<4; x++) {
261                         colch[x] = FTOCHAR(col[x]);
262                 }
263                 
264                 max = buf + (4 * (w * h));
265                 while ((c = (unsigned char) *str++)) {
266                         BMF_CharData & cd = m_fontData->chars[c];
267                         if (cd.data_offset != -1) { 
268                                 for (y = 0; y < cd.height; y++) {
269                                         unsigned char* chrRow = &m_fontData->bitmap_data[cd.data_offset + ((cd.width+7)/8)*y];
270                                         for (x = cd.xorig; x < cd.width; x++) {
271                                                 pixel = buf + 4 * (((posy + y - cd.yorig) * w) + (posx + x));
272                                                 if ((pixel < max) && (pixel > buf)) {
273                                                         int byteIdx = x/8;
274                                                         int bitIdx = 7 - (x%8);
275                                                         
276                                                         if (chrRow[byteIdx]&(1<<bitIdx)) {
277                                                                 pixel[0] = colch[0];
278                                                                 pixel[1] = colch[1];
279                                                                 pixel[2] = colch[2];
280                                                                 pixel[4] = 1; /*colch[3];*/
281                                                                 
282                                                         }
283                                                 }
284                                         }
285                                 }
286                         }
287                         posx += cd.advance;
288                 }
289         }
290         
291         if (fbuf) {
292                 float *pixel, *max;
293                 unsigned char c;
294                 int x, y;
295                 
296                 max = fbuf + (4 * (w * h));
297                 
298                 while ((c = (unsigned char) *str++)) {
299                         BMF_CharData & cd = m_fontData->chars[c];
300                         if (cd.data_offset != -1) { 
301                                 for (y = 0; y < cd.height; y++) {
302                                         unsigned char* chrRow = &m_fontData->bitmap_data[cd.data_offset + ((cd.width+7)/8)*y];
303                                         for (x = cd.xorig; x < cd.width; x++) {
304                                                 pixel = fbuf + 4 * (((posy + y - cd.yorig) * w) + (posx + x));
305                                                 if ((pixel < max) && (pixel > fbuf)) {
306                                                         int byteIdx = x/8;
307                                                         int bitIdx = 7 - (x%8);
308                                                         
309                                                         if (chrRow[byteIdx]&(1<<bitIdx)) {
310                                                                 pixel[0] = col[0];
311                                                                 pixel[1] = col[1];
312                                                                 pixel[2] = col[2];
313                                                                 pixel[3] = 1; /*col[3];*/
314                                                         }
315                                                 }
316                                         }
317                                 }
318                         }
319                         posx += cd.advance;
320                 }
321         }
322 }