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