1 /*
2 * c-demo.cpp - simple C demo for FTGL, the OpenGL font library
3 *
4 * Copyright (c) 2008 Sam Hocevar <sam@hocevar.net>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26 #include "config.h"
27
28 #include <math.h> /* sin(), cos() */
29 #include <stdlib.h> /* exit() */
30
31 #if defined HAVE_GL_GLUT_H
32 # include <GL/glut.h>
33 #elif defined HAVE_GLUT_GLUT_H
34 # include <GLUT/glut.h>
35 #else
36 # error GLUT headers not present
37 #endif
38
39 #include <FTGL/ftgl.h>
40
41 static FTGLfont *font[3];
42 static int fontindex = 0;
43 static int lastfps = 0;
44 static int frames = 0;
45
46 /*
47 * HaloGlyph is a derivation of FTGLglyph that displays a polygon glyph
48 * and a halo of outline glyphs at varying positions and with varying
49 * outset values.
50 */
51 struct HaloGlyph
52 {
53 FTGLglyph *subglyph[5];
54 };
55
RenderHalo(FTGLglyph * baseGlyph,void * data,FTGL_DOUBLE penx,FTGL_DOUBLE peny,int renderMode,FTGL_DOUBLE * advancex,FTGL_DOUBLE * advancey)56 static void RenderHalo(FTGLglyph * baseGlyph, void *data,
57 FTGL_DOUBLE penx, FTGL_DOUBLE peny, int renderMode,
58 FTGL_DOUBLE *advancex, FTGL_DOUBLE *advancey)
59 {
60 struct HaloGlyph *p = (struct HaloGlyph *)data;
61 int i;
62
63 glPushMatrix();
64 for(i = 0; i < 5; i++)
65 {
66 glTranslatef(0.0f, 0.0f, -2.0f);
67 ftglRenderGlyph(p->subglyph[i], penx, peny, renderMode,
68 advancex, advancey);
69 }
70 glPopMatrix();
71
72 ftglRenderGlyph(baseGlyph, penx, peny, renderMode, advancex, advancey);
73 }
74
DestroyHalo(FTGLglyph * baseGlyph,void * data)75 static void DestroyHalo(FTGLglyph * baseGlyph, void *data)
76 {
77 struct HaloGlyph *p = (struct HaloGlyph *)data;
78 int i;
79
80 for(i = 0; i < 5; i++)
81 {
82 ftglDestroyGlyph(p->subglyph[i]);
83 }
84
85 ftglDestroyGlyph(baseGlyph);
86 free(p);
87 }
88
MakeHaloGlyph(FT_GlyphSlot slot,void * data)89 static FTGLglyph *MakeHaloGlyph(FT_GlyphSlot slot, void *data)
90 {
91 (void) data;
92 struct HaloGlyph *p = malloc(sizeof(struct HaloGlyph));
93 FTGLglyph *baseGlyph = ftglCreatePolygonGlyph(slot, 0.0f, 1.0f);
94 int i;
95
96 for(i = 0; i < 5; i++)
97 {
98 p->subglyph[i] = ftglCreateOutlineGlyph(slot, i, 1);
99 }
100
101 return ftglCreateCustomGlyph(baseGlyph, p, RenderHalo, DestroyHalo);
102 }
103
104 /*
105 * Main OpenGL loop: set up lights, apply a few rotation effects, and
106 * render text using the current FTGL object.
107 */
RenderScene(void)108 static void RenderScene(void)
109 {
110 int now = glutGet(GLUT_ELAPSED_TIME);
111
112 float n = (float)now / 20.0f;
113 float t1 = sin(n / 80.0f);
114 float t2 = sin(n / 50.0f + 1.0f);
115 float t3 = sin(n / 30.0f + 2.0f);
116
117 float ambient[4] = { (t1 + 2.0f) / 3.0f,
118 (t2 + 2.0f) / 3.0f,
119 (t3 + 2.0f) / 3.0f, 0.3f };
120 float diffuse[4] = { 1.0f, 0.9f, 0.9f, 1.0f };
121 float specular[4] = { 1.0f, 0.7f, 0.7f, 1.0f };
122 float position[4] = { 100.0f, 100.0f, 0.0f, 1.0f };
123
124 float front_ambient[4] = { 0.7f, 0.7f, 0.7f, 0.0f };
125
126 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
127
128 glEnable(GL_LIGHTING);
129 glEnable(GL_DEPTH_TEST);
130 glEnable(GL_LINE_SMOOTH);
131 glEnable(GL_BLEND);
132 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
133
134 glPushMatrix();
135 glTranslatef(-0.9f, -0.2f, -10.0f);
136 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
137 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
138 glLightfv(GL_LIGHT1, GL_SPECULAR, specular);
139 glLightfv(GL_LIGHT1, GL_POSITION, position);
140 glEnable(GL_LIGHT1);
141 glPopMatrix();
142
143 glPushMatrix();
144 glMaterialfv(GL_FRONT, GL_AMBIENT, front_ambient);
145 glColorMaterial(GL_FRONT, GL_DIFFUSE);
146 glTranslatef(0.0f, 0.0f, 20.0f);
147 glRotatef(n / 1.11f, 0.0f, 1.0f, 0.0f);
148 glRotatef(n / 2.23f, 1.0f, 0.0f, 0.0f);
149 glRotatef(n / 3.17f, 0.0f, 0.0f, 1.0f);
150 glTranslatef(-260.0f, -0.2f, 0.0f);
151 glColor3f(0.0f, 0.0f, 0.0f);
152 ftglRenderFont(font[fontindex], "Hello FTGL!", FTGL_RENDER_ALL);
153 glPopMatrix();
154
155 glutSwapBuffers();
156
157 frames++;
158
159 if(now - lastfps > 5000)
160 {
161 fprintf(stderr, "%i frames in 5.0 seconds = %g FPS\n",
162 frames, frames * 1000. / (now - lastfps));
163 lastfps += 5000;
164 frames = 0;
165 }
166 }
167
168 /*
169 * GLUT key processing function: <esc> quits, <tab> cycles across fonts.
170 */
ProcessKeys(unsigned char key,int x,int y)171 static void ProcessKeys(unsigned char key, int x, int y)
172 {
173 (void) x;
174 (void) y;
175 switch(key)
176 {
177 case 27:
178 ftglDestroyFont(font[0]);
179 ftglDestroyFont(font[1]);
180 ftglDestroyFont(font[2]);
181 exit(EXIT_SUCCESS);
182 break;
183 case '\t':
184 fontindex = (fontindex + 1) % 3;
185 break;
186 }
187 }
188
189 /*
190 * Main program entry point: set up GLUT window, load fonts, run GLUT loop.
191 */
main(int argc,char ** argv)192 int main(int argc, char **argv)
193 {
194 char const *file = NULL;
195
196 #ifdef FONT_FILE
197 file = FONT_FILE;
198 #else
199 if(argc < 2)
200 {
201 fprintf(stderr, "Usage: %s <font_name.ttf>\n", argv[0]);
202 return EXIT_FAILURE;
203 }
204 #endif
205
206 if(argc > 1)
207 {
208 file = argv[1];
209 }
210
211 /* Initialise GLUT stuff */
212 glutInit(&argc, argv);
213 glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
214 glutInitWindowPosition(100, 100);
215 glutInitWindowSize(640, 480);
216 glutCreateWindow("simple FTGL C demo");
217
218 glutDisplayFunc(RenderScene);
219 glutIdleFunc(RenderScene);
220 glutKeyboardFunc(ProcessKeys);
221
222 glMatrixMode(GL_PROJECTION);
223 glLoadIdentity();
224 gluPerspective(90, 640.0f / 480.0f, 1, 1000);
225 glMatrixMode(GL_MODELVIEW);
226 glLoadIdentity();
227 gluLookAt(0.0, 0.0, 640.0f / 2.0f, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
228
229 /* Initialise FTGL stuff */
230 font[0] = ftglCreateExtrudeFont(file);
231 font[1] = ftglCreateBufferFont(file);
232 font[2] = ftglCreateCustomFont(file, NULL, MakeHaloGlyph);
233 if(!font[0] || !font[1] || !font[2])
234 {
235 fprintf(stderr, "%s: could not load font `%s'\n", argv[0], file);
236 return EXIT_FAILURE;
237 }
238
239 ftglSetFontFaceSize(font[0], 80, 72);
240 ftglSetFontDepth(font[0], 10);
241 ftglSetFontOutset(font[0], 0, 3);
242 ftglSetFontCharMap(font[0], ft_encoding_unicode);
243
244 ftglSetFontFaceSize(font[1], 80, 72);
245 ftglSetFontCharMap(font[1], ft_encoding_unicode);
246
247 ftglSetFontFaceSize(font[2], 80, 72);
248 ftglSetFontCharMap(font[2], ft_encoding_unicode);
249
250 fprintf(stderr, "Using FTGL version %s\n",
251 ftglGetString(FTGL_CONFIG_VERSION));
252
253 /* Run GLUT loop */
254 glutMainLoop();
255
256 return EXIT_SUCCESS;
257 }
258
259