3 * @brief The text display module for gljewel
5 * Copyright 2001, 2008 David Ashley <dashxdr@gmail.com>
6 * Copyright 2008 Stephen M. Webb <stephen.webb@bregmasoft.ca>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of Version 2 of the GNU General Public License as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #if defined(_WIN32) && !defined(__CYGWIN__)
24 # define WIN32_LEAN_AND_MEAN 1
34 typedef unsigned int uint32
;
36 /* Maps ASCII characters to indexes into font texture. */
38 #define UNDEFINED_CHAR 0xff
42 static char *fontcharacters
="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.!:>^@() +";
46 memset(lmap
, UNDEFINED_CHAR
, sizeof(lmap
));
47 for (p
= fontcharacters
; *p
; ++p
)
53 static GLint fontlist
;
64 static struct letter
{
65 unsigned char px
,py
,sx
,sy
;
70 static unsigned int textures
[10];
72 #define T_HEIGHT T_WIDTH
75 void drawstring(int align
, char *fmt
, ...)
83 vsprintf(temp
,fmt
,ap
);
87 glDisable(GL_DEPTH_TEST
);
89 glEnable(GL_TEXTURE_2D
);
90 glBindTexture(GL_TEXTURE_2D
,textures
[0]);
92 glNormal3f( 0.0, 0.0, 1.0);
100 if((t
=lmap
[(int)*p
++])!=-1)
101 advance
+=letters
[t
].advance
;
103 if(align
==1) advance
/=2.0;
104 glTranslatef(-advance
,0.0, 0.0);
109 if((t
=lmap
[(int)*p
++])!=-1)
110 glCallList(fontlist
+t
);
112 glDisable(GL_TEXTURE_2D
);
115 glEnable(GL_DEPTH_TEST
);
121 static unsigned char ppmbuff
[2048],*ppmp
;
128 ppmin
=fread(ppmbuff
,sizeof(char),sizeof(ppmbuff
),ppmh
);
131 if(ppmin
<=0) return -1;
137 static void ppmline(unsigned char *put
)
140 while((c
=ppmci())>=0)
147 * A PPM file consists of a sequence of one or more PPM images. There are no data, delimiters, or padding before, after, or between images.
149 * Each PPM image consists of the following:
151 * 1. A "magic number" for identifying the file type. A ppm image's magic
152 * number is the two characters "P6".
153 * 2. Whitespace (blanks, TABs, CRs, LFs).
154 * 3. A width, formatted as ASCII characters in decimal.
156 * 5. A height, again in ASCII decimal.
158 * 7. The maximum color value (Maxval), again in ASCII decimal. Must be less
159 * than 65536 and more than zero.
160 * 8. A single whitespace character (usually a newline).
161 * 9. A raster of Height rows, in order from top to bottom. Each row consists
162 * of Width pixels, in order from left to right. Each pixel is a triplet of
163 * red, green, and blue samples, in that order. Each sample is represented
164 * in pure binary by either 1 or 2 bytes. If the Maxval is less than 256,
165 * it is 1 byte. Otherwise, it is 2 bytes. The most significant byte is first.
167 * A row of an image is horizontal. A column is vertical. The pixels in the
168 * image are square and contiguous.
169 * 10. In the raster, the sample values are "nonlinear." They are proportional
170 * to the intensity of the ITU-R Recommendation BT.709 red, green, and blue
171 * in the pixel, adjusted by the BT.709 gamma transfer function. (That
172 * transfer function specifies a gamma number of 2.2 and has a linear
173 * section for small intensities). A value of Maxval for all three samples
174 * represents CIE D65 white and the most intense color in the color universe
175 * of which the image is part (the color universe is all the colors in all
176 * images to which this image might be compared).
178 * ITU-R Recommendation BT.709 is a renaming of the former CCIR Recommendation
179 * 709. When CCIR was absorbed into its parent organization, the ITU, ca. 2000,
180 * the standard was renamed. This document once referred to the standard as CIE
181 * Rec. 709, but it isn't clear now that CIE ever sponsored such a standard.
183 * Note that another popular color space is the newer sRGB. A common variation
184 * on PPM is to subsitute this color space for the one specified.
185 * 11. Note that a common variation on the PPM format is to have the sample values
186 * be "linear," i.e. as specified above except without the gamma adjustment.
187 * pnmgamma takes such a PPM variant as input and produces a true PPM as output.
188 * 12. Strings starting with "#" may be comments, the same as with PBM.
190 static int readppm(char *name
,struct pic
*pic
)
192 unsigned char line
[8192];
199 ppmh
=fopen(name
,"r");
202 fprintf(stderr
, "error %d reading \"%s\": %s\n",
203 errno
, name
, strerror(errno
));
209 if(strcmp((char *)line
,"P6")) {fclose(ppmh
);return 0;}
211 /* get width and height */
213 if(sscanf((char *)line
,"%d %d",&w
,&h
)!=2) {fclose(ppmh
);return 0;}
215 /* get max colour value */
217 if (sscanf(line
, "%d", &maxval
) != 1) {fclose(ppmh
); return 0; }
220 fprintf(stderr
, "max colour value %d out of range in PPM file \"%s\"\n",
226 pic
->image
=put
=malloc(w
*h
*3);
227 if(!put
) {fclose(ppmh
);return 0;}
235 *put
++=ppmci(); /* red */
236 *put
++=ppmci(); /* green */
237 *put
++=ppmci(); /* blue */
243 static int loadfont(struct pic
*pic
)
246 char *fontfile
= "data/bigfont.ppm";
247 if (stat(fontfile
, &sbuf
))
249 fontfile
= DATA_DIR
"/bigfont.ppm";
250 if (stat(fontfile
, &sbuf
))
255 return readppm(fontfile
,pic
);
262 unsigned char keyr
,keyg
,keyb
,*p
;
263 unsigned char gapr
,gapg
,gapb
,r
,g
,b
;
271 fontlist
= glGenLists(MAXCHARS
);
273 tpixels
=malloc(T_WIDTH
*T_HEIGHT
*4);
274 memset(tpixels
,0,T_WIDTH
*T_HEIGHT
*4);
276 if(!loadfont(&pic
)) return;
278 /* pick out colorkey value from font image */
279 p
=pic
.image
+3*(pic
.w
*pic
.h
-1);
297 if(r
!=gapr
|| g
!=gapg
|| b
!=gapb
) {++j
;continue;}
318 for(y
=0;y
<fontheight
;++y
)
322 t
=tpixels
+(yp
+y
)*T_WIDTH
+xp
;
323 p
=pic
.image
+3*(pic
.w
*(y
+1)+j
);
329 if(r
==keyr
&& g
==keyg
&& b
==keyb
)
332 *t
++=r
| (g
<<8) | (b
<<16) | (255<<24);
339 glGenTextures( 1, textures
);
340 glBindTexture( GL_TEXTURE_2D
, textures
[0] );
342 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
343 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
344 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
345 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
346 glTexImage2D( GL_TEXTURE_2D
, 0, 4, T_WIDTH
, T_HEIGHT
, 0, GL_RGBA
,
347 GL_UNSIGNED_BYTE
, tpixels
);
352 const float sizex
=2.0f
*FONTSIZE
*l
->sx
;
353 const float sizey
=FONTSIZE
*l
->sy
;
354 const float sx
=l
->px
/(float)T_WIDTH
;
355 const float sy
=l
->py
/(float)T_HEIGHT
;
356 const float ex
=(l
->px
+l
->sx
-1)/(float)T_WIDTH
;
357 const float ey
=(l
->py
+l
->sy
-1)/(float)T_HEIGHT
;
359 glNewList(fontlist
+i
, GL_COMPILE
);
361 /* row = (x, y, u, v) */
363 0.0f
, -sizey
, sx
, ey
,
364 sizex
, -sizey
, ex
, ey
,
369 const GLsizei row_width
= (2*2);
370 const GLsizei stride
= (row_width
* sizeof(GLfloat
));
371 const GLsizei vertex_count
= 4;
373 glEnableClientState(GL_VERTEX_ARRAY
);
374 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
375 glVertexPointer(2, GL_FLOAT
, stride
, v
);
376 glTexCoordPointer(2, GL_FLOAT
, stride
, v
+ 2);
377 glDrawArrays(GL_TRIANGLE_STRIP
, 0, vertex_count
);
378 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
379 glDisableClientState(GL_VERTEX_ARRAY
);
381 l
->advance
=FONTSIZE
*2+sizex
;
382 glTranslatef(l
->advance
, 0.0f
, 0.0f
);