1 | /* |
2 | * fg_font.c |
3 | * |
4 | * Bitmap and stroke fonts displaying. |
5 | * |
6 | * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. |
7 | * Written by Pawel W. Olszta, <olszta@sourceforge.net> |
8 | * Creation date: Thu Dec 16 1999 |
9 | * |
10 | * Permission is hereby granted, free of charge, to any person obtaining a |
11 | * copy of this software and associated documentation files (the "Software"), |
12 | * to deal in the Software without restriction, including without limitation |
13 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
14 | * and/or sell copies of the Software, and to permit persons to whom the |
15 | * Software is furnished to do so, subject to the following conditions: |
16 | * |
17 | * The above copyright notice and this permission notice shall be included |
18 | * in all copies or substantial portions of the Software. |
19 | * |
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
21 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
23 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
24 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
25 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
26 | */ |
27 | |
28 | #include <GL/freeglut.h> |
29 | #include "fg_internal.h" |
30 | |
31 | /* |
32 | * TODO BEFORE THE STABLE RELEASE: |
33 | * |
34 | * Test things out ... |
35 | */ |
36 | |
37 | /* -- IMPORT DECLARATIONS -------------------------------------------------- */ |
38 | |
39 | /* |
40 | * These are the font faces defined in fg_font_data.c file: |
41 | */ |
42 | extern SFG_Font fgFontFixed8x13; |
43 | extern SFG_Font fgFontFixed9x15; |
44 | extern SFG_Font fgFontHelvetica10; |
45 | extern SFG_Font fgFontHelvetica12; |
46 | extern SFG_Font fgFontHelvetica18; |
47 | extern SFG_Font fgFontTimesRoman10; |
48 | extern SFG_Font fgFontTimesRoman24; |
49 | extern SFG_StrokeFont fgStrokeRoman; |
50 | extern SFG_StrokeFont fgStrokeMonoRoman; |
51 | |
52 | |
53 | /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ |
54 | |
55 | /* |
56 | * Matches a font ID with a SFG_Font structure pointer. |
57 | * This was changed to match the GLUT header style. |
58 | */ |
59 | SFG_Font* fghFontByID( void* font ) |
60 | { |
61 | if( font == GLUT_BITMAP_8_BY_13 ) |
62 | return &fgFontFixed8x13; |
63 | if( font == GLUT_BITMAP_9_BY_15 ) |
64 | return &fgFontFixed9x15; |
65 | if( font == GLUT_BITMAP_HELVETICA_10 ) |
66 | return &fgFontHelvetica10; |
67 | if( font == GLUT_BITMAP_HELVETICA_12 ) |
68 | return &fgFontHelvetica12; |
69 | if( font == GLUT_BITMAP_HELVETICA_18 ) |
70 | return &fgFontHelvetica18; |
71 | if( font == GLUT_BITMAP_TIMES_ROMAN_10 ) |
72 | return &fgFontTimesRoman10; |
73 | if( font == GLUT_BITMAP_TIMES_ROMAN_24 ) |
74 | return &fgFontTimesRoman24; |
75 | |
76 | return 0; |
77 | } |
78 | |
79 | /* |
80 | * Matches a font ID with a SFG_StrokeFont structure pointer. |
81 | * This was changed to match the GLUT header style. |
82 | */ |
83 | static SFG_StrokeFont* fghStrokeByID( void* font ) |
84 | { |
85 | if( font == GLUT_STROKE_ROMAN ) |
86 | return &fgStrokeRoman; |
87 | if( font == GLUT_STROKE_MONO_ROMAN ) |
88 | return &fgStrokeMonoRoman; |
89 | |
90 | return 0; |
91 | } |
92 | |
93 | |
94 | /* -- INTERFACE FUNCTIONS -------------------------------------------------- */ |
95 | |
96 | /* |
97 | * Draw a bitmap character |
98 | */ |
99 | void FGAPIENTRY glutBitmapCharacter( void* fontID, int character ) |
100 | { |
101 | const GLubyte* face; |
102 | SFG_Font* font; |
103 | FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutBitmapCharacter" ); |
104 | font = fghFontByID( fontID ); |
105 | if (!font) |
106 | { |
107 | fgWarning("glutBitmapCharacter: bitmap font 0x%08x not found. Make sure you're not passing a stroke font.\n" ,fontID); |
108 | return; |
109 | } |
110 | freeglut_return_if_fail( ( character >= 1 )&&( character < 256 ) ); |
111 | |
112 | /* |
113 | * Find the character we want to draw (???) |
114 | */ |
115 | face = font->Characters[ character ]; |
116 | |
117 | glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT ); |
118 | glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE ); |
119 | glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE ); |
120 | glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 ); |
121 | glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 ); |
122 | glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 ); |
123 | glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); |
124 | glBitmap( |
125 | face[ 0 ], font->Height, /* The bitmap's width and height */ |
126 | font->xorig, font->yorig, /* The origin in the font glyph */ |
127 | ( float )( face[ 0 ] ), 0.0, /* The raster advance -- inc. x,y */ |
128 | ( face + 1 ) /* The packed bitmap data... */ |
129 | ); |
130 | glPopClientAttrib( ); |
131 | } |
132 | |
133 | void FGAPIENTRY glutBitmapString( void* fontID, const unsigned char *string ) |
134 | { |
135 | unsigned char c; |
136 | float x = 0.0f ; |
137 | SFG_Font* font; |
138 | FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutBitmapString" ); |
139 | font = fghFontByID( fontID ); |
140 | if (!font) |
141 | { |
142 | fgWarning("glutBitmapString: bitmap font 0x%08x not found. Make sure you're not passing a stroke font.\n" ,fontID); |
143 | return; |
144 | } |
145 | if ( !string || ! *string ) |
146 | return; |
147 | |
148 | glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT ); |
149 | glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE ); |
150 | glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE ); |
151 | glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 ); |
152 | glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 ); |
153 | glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 ); |
154 | glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); |
155 | |
156 | /* |
157 | * Step through the string, drawing each character. |
158 | * A newline will simply translate the next character's insertion |
159 | * point back to the start of the line and down one line. |
160 | */ |
161 | while( ( c = *string++) ) |
162 | if( c == '\n' ) |
163 | { |
164 | glBitmap ( 0, 0, 0, 0, -x, (float) -font->Height, NULL ); |
165 | x = 0.0f; |
166 | } |
167 | else /* Not an EOL, draw the bitmap character */ |
168 | { |
169 | const GLubyte* face = font->Characters[ c ]; |
170 | |
171 | glBitmap( |
172 | face[ 0 ], font->Height, /* Bitmap's width and height */ |
173 | font->xorig, font->yorig, /* The origin in the font glyph */ |
174 | ( float )( face[ 0 ] ), 0.0, /* The raster advance; inc. x,y */ |
175 | ( face + 1 ) /* The packed bitmap data... */ |
176 | ); |
177 | |
178 | x += ( float )( face[ 0 ] ); |
179 | } |
180 | |
181 | glPopClientAttrib( ); |
182 | } |
183 | |
184 | /* |
185 | * Returns the width in pixels of a font's character |
186 | */ |
187 | int FGAPIENTRY glutBitmapWidth( void* fontID, int character ) |
188 | { |
189 | SFG_Font* font; |
190 | FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutBitmapWidth" ); |
191 | freeglut_return_val_if_fail( character > 0 && character < 256, 0 ); |
192 | font = fghFontByID( fontID ); |
193 | if (!font) |
194 | { |
195 | fgWarning("glutBitmapWidth: bitmap font 0x%08x not found. Make sure you're not passing a stroke font.\n" ,fontID); |
196 | return 0; |
197 | } |
198 | return *( font->Characters[ character ] ); |
199 | } |
200 | |
201 | /* |
202 | * Return the width of a string drawn using a bitmap font |
203 | */ |
204 | int FGAPIENTRY glutBitmapLength( void* fontID, const unsigned char* string ) |
205 | { |
206 | unsigned char c; |
207 | int length = 0, this_line_length = 0; |
208 | SFG_Font* font; |
209 | FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutBitmapLength" ); |
210 | font = fghFontByID( fontID ); |
211 | if (!font) |
212 | { |
213 | fgWarning("glutBitmapLength: bitmap font 0x%08x not found. Make sure you're not passing a stroke font.\n" ,fontID); |
214 | return 0; |
215 | } |
216 | if ( !string || ! *string ) |
217 | return 0; |
218 | |
219 | while( ( c = *string++) ) |
220 | { |
221 | if( c != '\n' )/* Not an EOL, increment length of line */ |
222 | this_line_length += *( font->Characters[ c ]); |
223 | else /* EOL; reset the length of this line */ |
224 | { |
225 | if( length < this_line_length ) |
226 | length = this_line_length; |
227 | this_line_length = 0; |
228 | } |
229 | } |
230 | if ( length < this_line_length ) |
231 | length = this_line_length; |
232 | |
233 | return length; |
234 | } |
235 | |
236 | /* |
237 | * Returns the height of a bitmap font |
238 | */ |
239 | int FGAPIENTRY glutBitmapHeight( void* fontID ) |
240 | { |
241 | SFG_Font* font; |
242 | FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutBitmapHeight" ); |
243 | font = fghFontByID( fontID ); |
244 | if (!font) |
245 | { |
246 | fgWarning("glutBitmapHeight: bitmap font 0x%08x not found. Make sure you're not passing a stroke font.\n" ,fontID); |
247 | return 0; |
248 | } |
249 | return font->Height; |
250 | } |
251 | |
252 | /* |
253 | * Draw a stroke character |
254 | */ |
255 | void FGAPIENTRY glutStrokeCharacter( void* fontID, int character ) |
256 | { |
257 | const SFG_StrokeChar *schar; |
258 | const SFG_StrokeStrip *strip; |
259 | int i, j; |
260 | SFG_StrokeFont* font; |
261 | FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeCharacter" ); |
262 | font = fghStrokeByID( fontID ); |
263 | if (!font) |
264 | { |
265 | fgWarning("glutStrokeCharacter: stroke font 0x%08x not found. Make sure you're not passing a bitmap font.\n" ,fontID); |
266 | return; |
267 | } |
268 | freeglut_return_if_fail( character >= 0 ); |
269 | freeglut_return_if_fail( character < font->Quantity ); |
270 | |
271 | schar = font->Characters[ character ]; |
272 | freeglut_return_if_fail( schar ); |
273 | strip = schar->Strips; |
274 | |
275 | for( i = 0; i < schar->Number; i++, strip++ ) |
276 | { |
277 | glBegin( GL_LINE_STRIP ); |
278 | for( j = 0; j < strip->Number; j++ ) |
279 | glVertex2f( strip->Vertices[ j ].X, strip->Vertices[ j ].Y ); |
280 | glEnd( ); |
281 | |
282 | if (fgState.StrokeFontDrawJoinDots) |
283 | { |
284 | glBegin( GL_POINTS ); |
285 | for( j = 0; j < strip->Number; j++ ) |
286 | glVertex2f( strip->Vertices[ j ].X, strip->Vertices[ j ].Y ); |
287 | glEnd( ); |
288 | } |
289 | } |
290 | glTranslatef( schar->Right, 0.0, 0.0 ); |
291 | } |
292 | |
293 | void FGAPIENTRY glutStrokeString( void* fontID, const unsigned char *string ) |
294 | { |
295 | unsigned char c; |
296 | int i, j; |
297 | float length = 0.0; |
298 | SFG_StrokeFont* font; |
299 | FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeString" ); |
300 | font = fghStrokeByID( fontID ); |
301 | if (!font) |
302 | { |
303 | fgWarning("glutStrokeString: stroke font 0x%08x not found. Make sure you're not passing a bitmap font.\n" ,fontID); |
304 | return; |
305 | } |
306 | if ( !string || ! *string ) |
307 | return; |
308 | |
309 | /* |
310 | * Step through the string, drawing each character. |
311 | * A newline will simply translate the next character's insertion |
312 | * point back to the start of the line and down one line. |
313 | */ |
314 | while( ( c = *string++) ) |
315 | if( c < font->Quantity ) |
316 | { |
317 | if( c == '\n' ) |
318 | { |
319 | glTranslatef ( -length, -( float )( font->Height ), 0.0 ); |
320 | length = 0.0; |
321 | } |
322 | else /* Not an EOL, draw the bitmap character */ |
323 | { |
324 | const SFG_StrokeChar *schar = font->Characters[ c ]; |
325 | if( schar ) |
326 | { |
327 | const SFG_StrokeStrip *strip = schar->Strips; |
328 | |
329 | for( i = 0; i < schar->Number; i++, strip++ ) |
330 | { |
331 | glBegin( GL_LINE_STRIP ); |
332 | for( j = 0; j < strip->Number; j++ ) |
333 | glVertex2f( strip->Vertices[ j ].X, |
334 | strip->Vertices[ j ].Y); |
335 | |
336 | glEnd( ); |
337 | } |
338 | |
339 | length += schar->Right; |
340 | glTranslatef( schar->Right, 0.0, 0.0 ); |
341 | } |
342 | } |
343 | } |
344 | } |
345 | |
346 | /* |
347 | * Return the width in pixels of a stroke character |
348 | */ |
349 | GLfloat FGAPIENTRY glutStrokeWidthf( void* fontID, int character ) |
350 | { |
351 | const SFG_StrokeChar *schar; |
352 | SFG_StrokeFont* font; |
353 | FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeWidth" ); |
354 | font = fghStrokeByID( fontID ); |
355 | if (!font) |
356 | { |
357 | fgWarning("glutStrokeWidth: stroke font 0x%08x not found. Make sure you're not passing a bitmap font.\n" ,fontID); |
358 | return 0; |
359 | } |
360 | freeglut_return_val_if_fail( ( character >= 0 ) && |
361 | ( character < font->Quantity ), |
362 | 0 |
363 | ); |
364 | schar = font->Characters[ character ]; |
365 | freeglut_return_val_if_fail( schar, 0 ); |
366 | |
367 | return schar->Right; |
368 | } |
369 | int FGAPIENTRY glutStrokeWidth(void* fontID, int character) |
370 | { |
371 | return ( int )( glutStrokeWidthf(fontID,character) + 0.5f ); |
372 | } |
373 | |
374 | /* |
375 | * Return the width of a string drawn using a stroke font |
376 | */ |
377 | GLfloat FGAPIENTRY glutStrokeLengthf( void* fontID, const unsigned char* string ) |
378 | { |
379 | unsigned char c; |
380 | GLfloat length = 0.0; |
381 | GLfloat this_line_length = 0.0; |
382 | SFG_StrokeFont* font; |
383 | FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeLength" ); |
384 | font = fghStrokeByID( fontID ); |
385 | if (!font) |
386 | { |
387 | fgWarning("glutStrokeLength: stroke font 0x%08x not found. Make sure you're not passing a bitmap font.\n" ,fontID); |
388 | return 0; |
389 | } |
390 | if ( !string || ! *string ) |
391 | return 0; |
392 | |
393 | while( ( c = *string++) ) |
394 | if( c < font->Quantity ) |
395 | { |
396 | if( c == '\n' ) /* EOL; reset the length of this line */ |
397 | { |
398 | if( length < this_line_length ) |
399 | length = this_line_length; |
400 | this_line_length = 0.0; |
401 | } |
402 | else /* Not an EOL, increment the length of this line */ |
403 | { |
404 | const SFG_StrokeChar *schar = font->Characters[ c ]; |
405 | if( schar ) |
406 | this_line_length += schar->Right; |
407 | } |
408 | } |
409 | if( length < this_line_length ) |
410 | length = this_line_length; |
411 | return length; |
412 | } |
413 | int FGAPIENTRY glutStrokeLength( void* fontID, const unsigned char* string ) |
414 | { |
415 | return( int )( glutStrokeLengthf(fontID,string) + 0.5f ); |
416 | } |
417 | |
418 | /* |
419 | * Returns the height of a stroke font |
420 | */ |
421 | GLfloat FGAPIENTRY glutStrokeHeight( void* fontID ) |
422 | { |
423 | SFG_StrokeFont* font; |
424 | FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeHeight" ); |
425 | font = fghStrokeByID( fontID ); |
426 | if (!font) |
427 | { |
428 | fgWarning("glutStrokeHeight: stroke font 0x%08x not found. Make sure you're not passing a bitmap font.\n" ,fontID); |
429 | return 0.f; |
430 | } |
431 | return font->Height; |
432 | } |
433 | |
434 | /*** END OF FILE ***/ |
435 | |