1 /* textobj.c
2 **
3 ** quad with text as texture using OpenGL
4 ** Copyright (C) 2001 Florian Berger
5 ** Email: harpin_floh@yahoo.de, florian.berger@jk.uni-linz.ac.at
6 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License Version 2 as
9 ** published by the Free Software Foundation;
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 */
21
22 #include"options.h"
23 #include"font.h"
24 #include"textobj.h"
25 #include <GL/gl.h>
26 #include <GL/glu.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #ifdef options_use_freetype
32
bulb_font(char * data,int w,int h)33 void bulb_font( char * data, int w, int h )
34 {
35 int x,y,i,w2,h2,index;
36 double d;
37
38 w2=5; h2=5;
39 for ( y=0 ; y<h ; y++ ) {
40 for ( x=0 ; x<w ; x++ ) {
41 d=0;
42 for ( i=0 ; i<w2*h2 ; i++ ) {
43 index = (y-h2/2+i/w2)*w+x-w2/2+i%w2;
44 if( index>0 && index<w*h ){
45 d += (unsigned char)data[index];
46 }
47 }
48 if(data[y*w+x]!=0)
49 data[y*w+x] = (double)((unsigned char)data[y*w+x])*d/(double)w2/(double)h2/255.0;
50 }
51 }
52 }
53
54
diff_x_font(char * data,int w,int h)55 void diff_x_font( char * data, int w, int h )
56 {
57 int x,y,w2,h2;
58 double d;
59
60 w2=5; h2=5;
61 for ( y=0 ; y<h ; y++ ) {
62 for ( x=0 ; x<w ; x++ ) {
63 d=(unsigned char)data[y*w+x]-(unsigned char)data[y*w+x+1];
64 data[y*w+x] = (double)((unsigned char)data[y*w+x])*(200.0-d)/255.0;
65 }
66 }
67 }
68
diff_xy_font(char * data,int w,int h)69 void diff_xy_font( char * data, int w, int h )
70 {
71 int x,y,w2,h2;
72 double d;
73
74 w2=5; h2=5;
75 for ( y=0 ; y<h ; y++ ) {
76 for ( x=0 ; x<w ; x++ ) {
77 d=(unsigned char)data[y*w+x]-(unsigned char)data[(y+1)*w+x+1];
78 data[y*w+x] = (double)((unsigned char)data[y*w+x])*(200.0-d)/255.0;
79 }
80 }
81 }
82
83
create_string_quad(char * str,char * fontname,int h,int * quad_id,int * tex_id,double * quad_w,double * quad_h)84 int create_string_quad( char * str, char * fontname, int h, int * quad_id, int * tex_id, double * quad_w, double * quad_h )
85 {
86 int quad_obj;
87 int texbind;
88 int texw,texh, width,height;
89 char * texdata;
90 double fact;
91 int w1,w2, h1,h2, nx,ny;
92 #define MAX_TEXW 256
93 #define MAX_TEXH 256
94
95 getStringPixmapFT( str, fontname, h, &texdata, &texw, &texh, &width, &height );
96 glGenTextures(1,&texbind);
97 /* nx=(width+MAX_TEX_W-1)/MAX_TEX_W;
98 ny=(width+MAX_TEX_H-1)/MAX_TEX_H;
99 w1 = MAX_TEX_W;
100 w2 = NEXT_POW_OF_2(MAX_TEX_W & (MAX_TEX_W-1));
101 h1 = MAX_TEX_H;
102 h2 = NEXT_POW_OF_2(MAX_TEX_H & (MAX_TEX_H-1));*/
103
104 /* texnr++;
105 texnr=nx*ny
106
107 for(iy=0;iy<ny;iy++){
108 for(ix=0;ix<nx;ix++){
109 glGenTextures(1,&texbind[texnr]);
110 }
111 }*/
112
113
114 // bulb_font(texdata, texw, texh);
115 // diff_xy_font(texdata, texw, texh);
116 // fprintf(stderr,"texw=%d,texh=%d,w=%d,h=%d\n",texw,texh,width,height);
117 glBindTexture(GL_TEXTURE_2D,texbind);
118 gluBuild2DMipmaps(GL_TEXTURE_2D, 1, texw, texh, GL_LUMINANCE,
119 GL_UNSIGNED_BYTE, texdata);
120 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
121 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
122 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, options_tex_min_filter);
123 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, options_tex_mag_filter);
124 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
125 free(texdata);
126 // fprintf(stderr,"-texbind=%d\n",texbind);
127
128 // fprintf(stderr,"texx=%f,texy=%f\n",(double)texw/(double)width,(double)texh/(double)height);
129 fact=(double)h;
130 quad_obj = glGenLists(1);
131 glNewList(quad_obj, GL_COMPILE);
132 // glBindTexture(GL_TEXTURE_2D,lightflaretexbind);
133 glBindTexture(GL_TEXTURE_2D,texbind);
134 glBegin(GL_QUADS);
135
136 glNormal3f(0,0,1);
137
138 glTexCoord2f(0,0);
139 glVertex3f(0,1.0*fact,0);
140
141 glTexCoord2f((double)width/(double)texw,0);
142 // glTexCoord2f(1,0);
143 // glTexCoord2f((double)texw/(double)width,0);
144 glVertex3f((double)width/(double)height*fact,1.0*fact,0);
145
146 glTexCoord2f((double)width/(double)texw,(double)height/(double)texh);
147 // glTexCoord2f(1,1);
148 // glTexCoord2f((double)texw/(double)width,(double)texh/(double)height);
149 glVertex3f((double)width/(double)height*fact,0,0);
150
151 glTexCoord2f(0,(double)height/(double)texh);
152 // glTexCoord2f(0,1);
153 // glTexCoord2f(0,(double)texh/(double)height);
154 glVertex3f(0,0,0);
155
156 glEnd();
157 glEndList();
158
159 *quad_h=fact*1.0;
160 *quad_w=(double)width/(double)height*fact;
161
162 if(quad_id!=0) *quad_id=quad_obj;
163 if(tex_id!=0) *tex_id=texbind;
164
165 return(quad_obj);
166 }
167
168
textObj_new(char * str,char * fontname,int height)169 textObj * textObj_new(char * str, char * fontname, int height )
170 {
171 textObj * obj;
172 obj=malloc(sizeof(textObj));
173 obj->height=height;
174 obj->depth3D=0.0; /* for toggling to 3D */
175 obj->is_3D=0;
176 strcpy(obj->str,str);
177 strcpy(obj->fontname,fontname);
178 create_string_quad( obj->str, obj->fontname, obj->height, &(obj->quad_id), &(obj->tex_id), &(obj->quad_w), &(obj->quad_h) );
179 return obj;
180 }
181
182
textObj3D_new(char * str,char * fontname,double height,float depth,int ppspline)183 textObj * textObj3D_new(char * str, char * fontname, double height, float depth, int ppspline)
184 {
185 textObj * obj;
186 obj=malloc(sizeof(textObj));
187 obj->height=height;
188 obj->depth3D=depth;
189 obj->is_3D=1;
190 strcpy(obj->str,str);
191 strcpy(obj->fontname,fontname);
192 obj->obj3D_id=getStringGLListFT( obj->str, obj->fontname, obj->height, obj->depth3D, &(obj->obj3D_w), &(obj->obj3D_h) );
193 return obj;
194 }
195
196
197
textObj_toggle3D(textObj * obj)198 void textObj_toggle3D( textObj * obj )
199 {
200 if(! obj->is_3D){
201 obj->is_3D=1;
202 glDeleteLists( obj->quad_id, 1 );
203 obj->quad_id=0;
204 glDeleteTextures( 1, &(obj->tex_id) );
205 obj->tex_id=0;
206 obj->obj3D_id=getStringGLListFT( obj->str, obj->fontname, obj->height, obj->depth3D, &(obj->obj3D_w), &(obj->obj3D_h) );
207 } else {
208 obj->is_3D=0;
209 glDeleteLists( obj->obj3D_id, 1 );
210 obj->obj3D_id=0;
211 create_string_quad( obj->str, obj->fontname, obj->height, &(obj->quad_id), &(obj->tex_id), &(obj->quad_w), &(obj->quad_h) );
212 }
213 }
214
215
textObj_setText(textObj * obj,char * str)216 void textObj_setText( textObj * obj, char * str )
217 {
218 if( strcmp(str,obj->str)!=0 ){
219 if(! obj->is_3D){
220 DPRINTF("textObj_setText: obj=%p, text=%s\n",obj, str);
221 DPRINTF("textObj_setText 0\n");
222 glDeleteLists( obj->quad_id, 1 );
223 DPRINTF("textObj_setText 0.5\n");
224 obj->quad_id=0;
225 DPRINTF("obj->tex_id=%d\n",obj->tex_id);
226 if( glIsTexture(obj->tex_id) == GL_TRUE )
227 glDeleteTextures( 1, &(obj->tex_id) );
228 DPRINTF("textObj_setText 0.75\n");
229 obj->tex_id=0;
230 strcpy(obj->str,str);
231 DPRINTF("textObj_setText 1\n");
232 create_string_quad( obj->str, obj->fontname, obj->height, &(obj->quad_id), &(obj->tex_id), &(obj->quad_w), &(obj->quad_h) );
233 DPRINTF("textObj_setText 2\n");
234 } else {
235 glDeleteLists( obj->obj3D_id, 1 );
236 obj->obj3D_id=0;
237 strcpy(obj->str,str);
238 obj->obj3D_id=getStringGLListFT( obj->str, obj->fontname, obj->height, obj->depth3D, &(obj->obj3D_w), &(obj->obj3D_h) );
239 }
240 }
241 }
242
243
textObj_delete_last(textObj * obj)244 void textObj_delete_last( textObj * obj )
245 {
246 char str[256];
247 int slen;
248 strcpy(str,obj->str);
249 slen = strlen(str);
250 str[slen-1]=0;
251 textObj_setText(obj,str);
252 }
253
textObj_append_char(textObj * obj,int c)254 void textObj_append_char( textObj * obj, int c )
255 {
256 char str[256];
257 int slen;
258 strcpy(str,obj->str);
259 slen = strlen(str);
260 str[slen+1]=0;
261 str[slen]=c;
262 textObj_setText(obj,str);
263 }
264
265
textObj_setHeight(textObj * obj,int height)266 void textObj_setHeight( textObj * obj, int height )
267 {
268 if(! obj->is_3D){
269 glDeleteLists( obj->quad_id, 1 );
270 obj->quad_id=0;
271 glDeleteTextures( 1, &(obj->tex_id) );
272 obj->tex_id=0;
273 obj->height=height;
274 create_string_quad( obj->str, obj->fontname, obj->height, &(obj->quad_id), &(obj->tex_id), &(obj->quad_w), &(obj->quad_h) );
275 } else {
276 glDeleteLists( obj->obj3D_id, 1 );
277 obj->obj3D_id=0;
278 obj->height=height;
279 obj->obj3D_id=getStringGLListFT( obj->str, obj->fontname, obj->height, obj->depth3D, &(obj->obj3D_w), &(obj->obj3D_h) );
280 }
281 }
282
textObj_setDepth(textObj * obj,int depth)283 void textObj_setDepth( textObj * obj, int depth )
284 {
285 if(! obj->is_3D){
286 obj->depth3D=depth;
287 } else {
288 glDeleteLists( obj->obj3D_id, 1 );
289 obj->obj3D_id=0;
290 obj->depth3D=depth;
291 obj->obj3D_id=getStringGLListFT( obj->str, obj->fontname, obj->height, obj->depth3D, &(obj->obj3D_w), &(obj->obj3D_h) );
292 }
293 }
294
textObj_setFont(textObj * obj,char * fontname)295 void textObj_setFont( textObj * obj, char * fontname )
296 {
297 if(! obj->is_3D){
298 glDeleteLists( obj->quad_id, 1 );
299 obj->quad_id=0;
300 glDeleteTextures( 1, &(obj->tex_id) );
301 obj->tex_id=0;
302 strcpy(obj->fontname,fontname);
303 create_string_quad( obj->str, obj->fontname, obj->height, &(obj->quad_id), &(obj->tex_id), &(obj->quad_w), &(obj->quad_h) );
304 } else {
305 glDeleteLists( obj->obj3D_id, 1 );
306 obj->obj3D_id=0;
307 strcpy(obj->fontname,fontname);
308 obj->obj3D_id=getStringGLListFT( obj->str, obj->fontname, obj->height, obj->depth3D, &(obj->obj3D_w), &(obj->obj3D_h) );
309 }
310 }
311
textObj_draw(textObj * obj)312 void textObj_draw( textObj * obj )
313 {
314 if(! obj->is_3D){
315 if( obj->quad_id != 0 )
316 glCallList( obj->quad_id );
317 } else {
318 if( obj->obj3D_id != 0 ){
319 // glDisable(GL_TEXTURE_2D);
320 glCallList( obj->obj3D_id );
321 // glEnable(GL_TEXTURE_2D);
322 }
323 }
324 }
325
textObj_draw_centered(textObj * obj)326 void textObj_draw_centered( textObj * obj )
327 {
328 if(! obj->is_3D){
329 glPushMatrix();
330 glTranslatef( -(double)(obj->quad_w)/2.0, -(double)(obj->quad_h)/2.0, 0.0 );
331 if( obj->quad_id != 0 )
332 glCallList( obj->quad_id );
333 glPopMatrix();
334 } else {
335 glPushMatrix();
336 glTranslatef( -(double)(obj->obj3D_w)/2.0, -(double)(obj->obj3D_h)/2.0, (double)(obj->depth3D)/2.0 );
337 if( obj->obj3D_id != 0 ){
338 // glDisable(GL_TEXTURE_2D);
339 glCallList( obj->obj3D_id );
340 // glEnable(GL_TEXTURE_2D);
341
342 }
343 glPopMatrix();
344 }
345 }
346
textObj_draw_bound(textObj * obj,int hbound,int vbound)347 void textObj_draw_bound( textObj * obj, int hbound, int vbound )
348 {
349 double x,y;
350 if(! obj->is_3D){
351 x=0.0;
352 y=0.0;
353 if( hbound == HBOUND_CENTER ) x=-(double)(obj->quad_w)/2.0;
354 if( hbound == HBOUND_RIGHT ) x=-(double)(obj->quad_w);
355 if( hbound == HBOUND_LEFT ) x=0.0;
356 if( vbound == VBOUND_CENTER ) y=-(double)(obj->quad_h)/2.0;
357 if( vbound == VBOUND_TOP ) y=-(double)(obj->quad_h);
358 if( vbound == VBOUND_BOTTOM ) y=0.0;
359 glPushMatrix();
360 glTranslatef( x, y, 0.0 );
361 if( obj->quad_id != 0 )
362 glCallList( obj->quad_id );
363 glPopMatrix();
364 } else {
365 x=0.0;
366 y=0.0;
367 if( hbound == HBOUND_CENTER ) x=-(double)(obj->obj3D_w)/2.0;
368 if( hbound == HBOUND_RIGHT ) x=-(double)(obj->obj3D_w);
369 if( hbound == HBOUND_LEFT ) x=0.0;
370 if( vbound == VBOUND_CENTER ) y=-(double)(obj->obj3D_h)/2.0;
371 if( vbound == VBOUND_TOP ) y=-(double)(obj->obj3D_h);
372 if( vbound == VBOUND_BOTTOM ) y=0.0;
373 glPushMatrix();
374 glTranslatef( x, y, 0.0 );
375 if( obj->obj3D_id != 0 ){
376 // glDisable(GL_TEXTURE_2D);
377 glCallList( obj->obj3D_id );
378 // glEnable(GL_TEXTURE_2D);
379 }
380 glPopMatrix();
381 }
382 }
383
textObj_delete(textObj * obj)384 void textObj_delete( textObj * obj )
385 {
386 if(! obj->is_3D){
387 glDeleteLists( obj->quad_id, 1 );
388 obj->quad_id=0;
389 glDeleteTextures( 1, &(obj->tex_id) );
390 obj->tex_id=0;
391 } else {
392 glDeleteLists( obj->obj3D_id, 1 );
393 obj->obj3D_id=0;
394 }
395 }
396
397 #endif
398