Commit e9260bbf4dd8cd5738955c10db02c1e9b494f299

sammy 2008-05-08T22:35:57

* Implement C bindings for FTGlyph and FTFont subclassing. * Add subclassing to the simple C demo to show how to do similar stuff as in the C++ demo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
diff --git a/demo/c-demo.c b/demo/c-demo.c
index 2316054..2a0ae8b 100644
--- a/demo/c-demo.c
+++ b/demo/c-demo.c
@@ -38,7 +38,65 @@
 
 #include <FTGL/ftgl.h>
 
-static FTGLfont *font;
+static FTGLfont *font[3];
+static int fontindex = 0;
+
+/*
+ * HaloGlyph is a derivation of FTGLglyph that displays a polygon glyph
+ * and a halo of outline glyphs at varying positions and with varying
+ * outset values.
+ */
+struct HaloGlyph
+{
+    FTGLglyph *subglyph[5];
+};
+
+static void RenderHalo(FTGLglyph * baseGlyph, void *data,
+                       FTGL_DOUBLE penx, FTGL_DOUBLE peny, int renderMode,
+                       FTGL_DOUBLE *advancex, FTGL_DOUBLE *advancey)
+{
+    struct HaloGlyph *p = (struct HaloGlyph *)data;
+    int i;
+
+    glPushMatrix();
+    for(i = 0; i < 5; i++)
+    {
+        glTranslatef(0.0, 0.0, -2.0);
+        ftglRenderGlyph(p->subglyph[i], penx, peny, renderMode,
+                        advancex, advancey);
+    }
+    glPopMatrix();
+
+    ftglRenderGlyph(baseGlyph, penx, peny, renderMode, advancex, advancey);
+}
+
+static void DestroyHalo(FTGLglyph * baseGlyph, void *data)
+{
+    struct HaloGlyph *p = (struct HaloGlyph *)data;
+    int i;
+
+    for(i = 0; i < 5; i++)
+    {
+        ftglDestroyGlyph(p->subglyph[i]);
+    }
+
+    ftglDestroyGlyph(baseGlyph);
+    free(p);
+}
+
+static FTGLglyph *MakeHaloGlyph(FT_GlyphSlot slot, void *data)
+{
+    struct HaloGlyph *p = malloc(sizeof(struct HaloGlyph));
+    FTGLglyph *baseGlyph = ftglCreatePolygonGlyph(slot, 0., 1);
+    int i;
+
+    for(i = 0; i < 5; i++)
+    {
+        p->subglyph[i] = ftglCreateOutlineGlyph(slot, i, 1);
+    }
+
+    return ftglCreateCustomGlyph(baseGlyph, p, RenderHalo, DestroyHalo);
+}
 
 /*
  * Main OpenGL loop: set up lights, apply a few rotation effects, and
@@ -81,7 +139,7 @@ static void RenderScene(void)
         glRotatef(n / 3.17, 0.0, 0.0, 1.0);
         glTranslatef(-260.0, -0.2, 0.0);
         glColor3f(0.0, 0.0, 0.0);
-        ftglRenderFont(font, "Hello FTGL!", FTGL_RENDER_ALL);
+        ftglRenderFont(font[fontindex], "Hello FTGL!", FTGL_RENDER_ALL);
     glPopMatrix();
 
     glutSwapBuffers();
@@ -95,9 +153,14 @@ static void ProcessKeys(unsigned char key, int x, int y)
     switch(key)
     {
     case 27:
-        ftglDestroyFont(font);
+        ftglDestroyFont(font[0]);
+        ftglDestroyFont(font[1]);
+        ftglDestroyFont(font[2]);
         exit(EXIT_SUCCESS);
         break;
+    case '\t':
+        fontindex = (fontindex + 1) % 3;
+        break;
     }
 }
 
@@ -117,7 +180,7 @@ int main(int argc, char **argv)
     glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
     glutInitWindowPosition(100, 100);
     glutInitWindowSize(640, 480);
-    glutCreateWindow("FTGL simple demo");
+    glutCreateWindow("simple FTGL C demo");
 
     glutDisplayFunc(RenderScene);
     glutIdleFunc(RenderScene);
@@ -131,17 +194,26 @@ int main(int argc, char **argv)
     gluLookAt(0.0, 0.0, 640.0f / 2.0f, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
 
     /* Initialise FTGL stuff */
-    font = ftglCreateExtrudeFont(argv[1]);
-    if(!font)
+    //font = ftglCreateExtrudeFont(argv[1]);
+    font[0] = ftglCreateExtrudeFont(argv[1]);
+    font[1] = ftglCreatePolygonFont(argv[1]);
+    font[2] = ftglCreateCustomFont(argv[1], NULL, MakeHaloGlyph);
+    if(!font[0] || !font[1] || !font[2])
     {
         fprintf(stderr, "%s: could not load font `%s'\n", argv[0], argv[1]);
         return EXIT_FAILURE;
     }
 
-    ftglSetFontFaceSize(font, 80, 72);
-    ftglSetFontDepth(font, 10);
-    ftglSetFontOutset(font, 0, 3);
-    ftglSetFontCharMap(font, ft_encoding_unicode);
+    ftglSetFontFaceSize(font[0], 80, 72);
+    ftglSetFontDepth(font[0], 10);
+    ftglSetFontOutset(font[0], 0, 3);
+    ftglSetFontCharMap(font[0], ft_encoding_unicode);
+
+    ftglSetFontFaceSize(font[1], 80, 72);
+    ftglSetFontCharMap(font[1], ft_encoding_unicode);
+
+    ftglSetFontFaceSize(font[2], 80, 72);
+    ftglSetFontCharMap(font[2], ft_encoding_unicode);
 
     /* Run GLUT loop */
     glutMainLoop();
diff --git a/demo/simple.cpp b/demo/simple.cpp
index 157b398..68e79f7 100644
--- a/demo/simple.cpp
+++ b/demo/simple.cpp
@@ -145,7 +145,9 @@ static void ProcessKeys(unsigned char key, int x, int y)
     switch(key)
     {
     case 27:
-        delete font[0]; delete font[1]; delete font[2];
+        delete font[0];
+        delete font[1];
+        delete font[2];
         exit(EXIT_SUCCESS);
         break;
     case '\t':
@@ -170,7 +172,7 @@ int main(int argc, char **argv)
     glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
     glutInitWindowPosition(100, 100);
     glutInitWindowSize(640, 480);
-    glutCreateWindow("FTGL simple demo");
+    glutCreateWindow("simple FTGL C++ demo");
 
     glutDisplayFunc(RenderScene);
     glutIdleFunc(RenderScene);
diff --git a/src/FTFont/FTFontGlue.cpp b/src/FTFont/FTFontGlue.cpp
index 2ebdb4b..f316875 100644
--- a/src/FTFont/FTFontGlue.cpp
+++ b/src/FTFont/FTFontGlue.cpp
@@ -71,6 +71,40 @@ C_TOR(ftglCreatePolygonFont, (const char *fontname),
 C_TOR(ftglCreateTextureFont, (const char *fontname),
       FTTextureFont, (fontname), FONT_TEXTURE);
 
+// FTCustomFont::FTCustomFont();
+class FTCustomFont : public FTFont
+{
+public:
+    FTCustomFont(char const *fontFilePath, void *p,
+                 FTGLglyph * (*makeglyph) (FT_GlyphSlot, void *))
+     : FTFont(fontFilePath),
+       data(p),
+       makeglyphCallback(makeglyph)
+    {}
+
+    ~FTCustomFont()
+    {}
+
+    FTGlyph* MakeGlyph(FT_GlyphSlot slot)
+    {
+        FTGLglyph *g = makeglyphCallback(slot, data);
+        FTGlyph *glyph = g->ptr;
+        // XXX: we no longer need g, and no one will free it for us. Not
+        // very elegant, and we need to make sure no one else will try to
+        // use it.
+        free(g);
+        return glyph;
+    }
+
+private:
+    void *data;
+    FTGLglyph *(*makeglyphCallback) (FT_GlyphSlot, void *);
+};
+
+C_TOR(ftglCreateCustomFont, (char const *fontFilePath, void *data,
+                   FTGLglyph * (*makeglyphCallback) (FT_GlyphSlot, void *)),
+      FTCustomFont, (fontFilePath, data, makeglyphCallback), FONT_CUSTOM);
+
 #define C_FUN(cret, cname, cargs, cxxerr, cxxname, cxxarg) \
     cret cname cargs \
     { \
@@ -81,6 +115,8 @@ C_TOR(ftglCreateTextureFont, (const char *fontname),
         } \
         switch(f->type) \
         { \
+            case FTGL::FONT_CUSTOM: \
+                return dynamic_cast<FTCustomFont*>(f->ptr)->cxxname cxxarg; \
             case FTGL::FONT_BITMAP: \
                 return dynamic_cast<FTBitmapFont*>(f->ptr)->cxxname cxxarg; \
             case FTGL::FONT_EXTRUDE: \
@@ -108,6 +144,8 @@ void ftglDestroyFont(FTGLfont *f)
     }
     switch(f->type)
     {
+        case FTGL::FONT_CUSTOM:
+            delete dynamic_cast<FTCustomFont*>(f->ptr); break;
         case FTGL::FONT_BITMAP:
             delete dynamic_cast<FTBitmapFont*>(f->ptr); break;
         case FTGL::FONT_EXTRUDE:
diff --git a/src/FTGL/FTFont.h b/src/FTGL/FTFont.h
index 8396f14..9dad775 100644
--- a/src/FTGL/FTFont.h
+++ b/src/FTGL/FTFont.h
@@ -348,6 +348,18 @@ struct _FTGLFont;
 typedef struct _FTGLfont FTGLfont;
 
 /**
+ * Create a custom FTGL font object.
+ *
+ * @param fontFilePath  The font file name.
+ * @param data  A pointer to private data that will be passed to callbacks.
+ * @param makeglyphCallback  A glyph-making callback function.
+ * @return  An FTGLfont* object.
+ */
+FTGL_EXPORT FTGLfont *ftglCreateCustomFont(char const *fontFilePath,
+                                           void *data,
+                   FTGLglyph * (*makeglyphCallback) (FT_GlyphSlot, void *));
+
+/**
  * Destroy an FTGL font object.
  *
  * @param font  An FTGLfont* object.
diff --git a/src/FTGL/FTGlyph.h b/src/FTGL/FTGlyph.h
index 5164838..ff8e437 100644
--- a/src/FTGL/FTGlyph.h
+++ b/src/FTGL/FTGlyph.h
@@ -132,6 +132,21 @@ struct _FTGLGlyph;
 typedef struct _FTGLglyph FTGLglyph;
 
 /**
+ * Create a custom FTGL glyph object.
+ * FIXME: maybe get rid of "base" and have advanceCallback etc. functions
+ *
+ * @param base  The base FTGLglyph* to subclass.
+ * @param data  A pointer to private data that will be passed to callbacks.
+ * @param renderCallback  A rendering callback function.
+ * @param destroyCallback  A callback function to be called upon destruction.
+ * @return  An FTGLglyph* object.
+ */
+FTGL_EXPORT FTGLglyph *ftglCreateCustomGlyph(FTGLglyph *base, void *data,
+    void (*renderCallback) (FTGLglyph *, void *, FTGL_DOUBLE, FTGL_DOUBLE,
+                             int, FTGL_DOUBLE *, FTGL_DOUBLE *),
+    void (*destroyCallback) (FTGLglyph *, void *));
+
+/**
  * Destroy an FTGL glyph object.
  *
  * @param glyph  An FTGLglyph* object.
diff --git a/src/FTGL/FTPolyGlyph.h b/src/FTGL/FTPolyGlyph.h
index 315972f..ce3b000 100644
--- a/src/FTGL/FTPolyGlyph.h
+++ b/src/FTGL/FTPolyGlyph.h
@@ -89,8 +89,8 @@ FTGL_BEGIN_C_DECLS
  *                       <code>false</code> turns OFF display lists.
  * @return  An FTGLglyph* object.
  */
-FTGL_EXPORT FTGLglyph *ftglCreatePolyGlyph(FT_GlyphSlot glyph, float outset,
-                               int useDisplayList);
+FTGL_EXPORT FTGLglyph *ftglCreatePolygonGlyph(FT_GlyphSlot glyph, float outset,
+                                              int useDisplayList);
 
 FTGL_END_C_DECLS
 
diff --git a/src/FTGlyph/FTGlyphGlue.cpp b/src/FTGlyph/FTGlyphGlue.cpp
index 874e7b2..73e9cc4 100644
--- a/src/FTGlyph/FTGlyphGlue.cpp
+++ b/src/FTGlyph/FTGlyphGlue.cpp
@@ -70,9 +70,9 @@ C_TOR(ftglCreatePixmapGlyph, (FT_GlyphSlot glyph),
       FTPixmapGlyph, (glyph), GLYPH_PIXMAP);
 
 // FTPolygonGlyph::FTPolygonGlyph();
-C_TOR(ftglCreatePolyGlyph, (FT_GlyphSlot glyph, float outset,
-                            int useDisplayList),
-      FTPolygonGlyph, (glyph, outset, (useDisplayList != 0)), GLYPH_OUTLINE);
+C_TOR(ftglCreatePolygonGlyph, (FT_GlyphSlot glyph, float outset,
+                               int useDisplayList),
+      FTPolygonGlyph, (glyph, outset, (useDisplayList != 0)), GLYPH_POLYGON);
 
 // FTTextureGlyph::FTTextureGlyph();
 C_TOR(ftglCreateTextureGlyph, (FT_GlyphSlot glyph, int id, int xOffset,
@@ -80,6 +80,57 @@ C_TOR(ftglCreateTextureGlyph, (FT_GlyphSlot glyph, int id, int xOffset,
       FTTextureGlyph, (glyph, id, xOffset, yOffset, width, height),
       GLYPH_TEXTURE);
 
+// FTCustomGlyph::FTCustomGlyph();
+class FTCustomGlyph : public FTGlyph
+{
+public:
+    FTCustomGlyph(FTGLglyph *base, void *p,
+                  void (*render) (FTGLglyph *, void *, FTGL_DOUBLE, FTGL_DOUBLE,
+                                  int, FTGL_DOUBLE *, FTGL_DOUBLE *),
+                  void (*destroy) (FTGLglyph *, void *))
+     : FTGlyph((FT_GlyphSlot)0),
+       baseGlyph(base),
+       data(p),
+       renderCallback(render),
+       destroyCallback(destroy)
+    {}
+
+    ~FTCustomGlyph()
+    {
+        destroyCallback(baseGlyph, data);
+    }
+
+    const FTPoint& Advance() const { return baseGlyph->ptr->Advance(); }
+
+    const FTPoint& Render(const FTPoint& pen, int renderMode)
+    {
+        FTGL_DOUBLE advancex, advancey;
+        renderCallback(baseGlyph, data, pen.X(), pen.Y(), renderMode,
+                       &advancex, &advancey);
+        advance = FTPoint(advancex, advancey);
+        return advance;
+    }
+
+    const FTBBox& BBox() const { return baseGlyph->ptr->BBox(); }
+
+    FT_Error Error() const { return baseGlyph->ptr->Error(); }
+
+private:
+    FTPoint advance;
+    FTGLglyph *baseGlyph;
+    void *data;
+    void (*renderCallback) (FTGLglyph *, void *, FTGL_DOUBLE, FTGL_DOUBLE,
+                            int, FTGL_DOUBLE *, FTGL_DOUBLE *);
+    void (*destroyCallback) (FTGLglyph *, void *);
+};
+
+C_TOR(ftglCreateCustomGlyph, (FTGLglyph *base, void *data,
+         void (*renderCallback) (FTGLglyph *, void *, FTGL_DOUBLE, FTGL_DOUBLE,
+                                 int, FTGL_DOUBLE *, FTGL_DOUBLE *),
+         void (*destroyCallback) (FTGLglyph *, void *)),
+      FTCustomGlyph, (base, data, renderCallback, destroyCallback),
+      GLYPH_CUSTOM);
+
 #define C_FUN(cret, cname, cargs, cxxerr, cxxname, cxxarg) \
     cret cname cargs \
     { \
@@ -90,6 +141,8 @@ C_TOR(ftglCreateTextureGlyph, (FT_GlyphSlot glyph, int id, int xOffset,
         } \
         switch(g->type) \
         { \
+            case FTGL::GLYPH_CUSTOM: \
+                return dynamic_cast<FTCustomGlyph*>(g->ptr)->cxxname cxxarg; \
             case FTGL::GLYPH_BITMAP: \
                 return dynamic_cast<FTBitmapGlyph*>(g->ptr)->cxxname cxxarg; \
             case FTGL::GLYPH_EXTRUDE: \
@@ -117,8 +170,8 @@ void ftglDestroyGlyph(FTGLglyph *g)
     }
     switch(g->type)
     {
-        case FTGL::GLYPH_BITMAP:
-            delete dynamic_cast<FTBitmapGlyph*>(g->ptr); break;
+        case FTGL::GLYPH_CUSTOM:
+            delete dynamic_cast<FTCustomGlyph*>(g->ptr); break;
         case FTGL::GLYPH_EXTRUDE:
             delete dynamic_cast<FTExtrudeGlyph*>(g->ptr); break;
         case FTGL::GLYPH_OUTLINE:
diff --git a/src/FTInternals.h b/src/FTInternals.h
index c53e9c2..310da24 100644
--- a/src/FTInternals.h
+++ b/src/FTInternals.h
@@ -92,6 +92,7 @@ FTGL_BEGIN_C_DECLS
 
 typedef enum
 {
+    GLYPH_CUSTOM,
     GLYPH_BITMAP,
     GLYPH_PIXMAP,
     GLYPH_OUTLINE,
@@ -108,6 +109,7 @@ struct _FTGLglyph
 
 typedef enum
 {
+    FONT_CUSTOM,
     FONT_BITMAP,
     FONT_PIXMAP,
     FONT_OUTLINE,