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