1 /**************************************************************************\
2  * Copyright (c) Kongsberg Oil & Gas Technologies AS
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32 
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #else /* No config.h? Hmm. Assume the freetype library is available for linking. */
36 #define FREETYPEGLUE_ASSUME_FREETYPE 1
37 #endif /* !HAVE_CONFIG_H */
38 
39 #include <cassert>
40 #include <cstdlib>
41 #include <cstring>
42 #include <cstdio>
43 
44 #include <cmath>
45 #include <cstddef>
46 
47 #include <sys/stat.h>
48 #ifdef HAVE_UNISTD_H
49 #include <unistd.h>
50 #endif /* HAVE_UNISTD_H */
51 #ifdef HAVE_SYS_TYPES_H
52 #include <sys/types.h>
53 #endif /* HAVE_SYS_TYPES_H */
54 
55 #ifdef HAVE_FONTCONFIG
56 #include <fontconfig/fontconfig.h>
57 #endif
58 
59 #ifdef HAVE_FREETYPE /* In case we're _not_ doing runtime linking. */
60 #define FREETYPEGLUE_ASSUME_FREETYPE 1
61 #include <ft2build.h>
62 #include <freetype/freetype.h>
63 #include <freetype/ftglyph.h>
64 #include <freetype/ftoutln.h>
65 #endif /* FREETYPEGLUE_ASSUME_FREETYPE */
66 
67 #include <Inventor/C/basic.h>
68 #include <Inventor/C/glue/dl.h>
69 #include <Inventor/C/tidbits.h>
70 #include <Inventor/C/errors/debugerror.h>
71 
72 #include "tidbitsp.h"
73 #include "glue/freetype.h"
74 #include "threads/threadsutilp.h"
75 
76 typedef int (*cc_fcglue_FcGetVersion_t)(void);
77 typedef FcPattern * (*cc_fcglue_FcNameParse_t)(const unsigned char * name);
78 typedef int (*cc_fcglue_FcConfigSubstitute_t)(void * config, FcPattern * p, FcMatchKind kind);
79 typedef void (*cc_fcglue_FcDefaultSubstitute_t)(FcPattern *pattern);
80 typedef FcPattern * (*cc_fcglue_FcFontMatch_t)(void * config, FcPattern * p, FcResult * result);
81 typedef FcResult (*cc_fcglue_FcPatternGetString_t)(const FcPattern * p, const char * object, int n, unsigned char ** s);
82 typedef void (*cc_fcglue_FcPatternDestroy_t)(FcPattern * p);
83 typedef void (*cc_fcglue_FcPatternPrint_t)(const FcPattern * p);
84 typedef int (*cc_fcglue_FcPatternAddDouble_t)(FcPattern *p, const char *object, double d);
85 
86 typedef struct {
87   int available;
88   cc_fcglue_FcGetVersion_t FcGetVersion;
89   cc_fcglue_FcNameParse_t FcNameParse;
90   cc_fcglue_FcConfigSubstitute_t FcConfigSubstitute;
91   cc_fcglue_FcDefaultSubstitute_t FcDefaultSubstitute;
92   cc_fcglue_FcFontMatch_t FcFontMatch;
93   cc_fcglue_FcPatternGetString_t FcPatternGetString;
94   cc_fcglue_FcPatternDestroy_t FcPatternDestroy;
95   cc_fcglue_FcPatternPrint_t FcPatternPrint;
96   cc_fcglue_FcPatternAddDouble_t FcPatternAddDouble;
97 } cc_fcglue_t;
98 
99 typedef FT_Error (*cc_ftglue_FT_Init_FreeType_t)(FT_Library * library);
100 typedef void (*cc_ftglue_FT_Library_Version_t)(void * library, int * major, int * minor, int * patch);
101 typedef FT_Error (*cc_ftglue_FT_Done_FreeType_t)(void * library);
102 typedef FT_Error (*cc_ftglue_FT_New_Face_t)(void * library, const char * filepathname, long faceindex, FT_Face * face);
103 typedef FT_Error (*cc_ftglue_FT_Done_Face_t)(void * face);
104 typedef FT_Error (*cc_ftglue_FT_Select_Charmap_t)(FT_Face face, int encoding);
105 typedef FT_Error (*cc_ftglue_FT_Set_Char_Size_t)(FT_Face face, long width, long height, unsigned int hres, unsigned int vres);
106 typedef void (*cc_ftglue_FT_Set_Transform_t)(FT_Face face, FT_Matrix * matrix, FT_Vector * delta);
107 typedef FT_UInt (*cc_ftglue_FT_Get_Char_Index_t)(FT_Face face, unsigned long charidx);
108 typedef FT_Error (*cc_ftglue_FT_Load_Glyph_t)(FT_Face face, unsigned int glyph, int32_t loadflags);
109 typedef FT_Error (*cc_ftglue_FT_Get_Kerning_t)(FT_Face face, unsigned int left, unsigned int right, unsigned int kernmode, FT_Vector * akerning);
110 typedef FT_Error (*cc_ftglue_FT_Get_Glyph_t)(void * glyphslot, FT_Glyph * glyph);
111 typedef FT_Error (*cc_ftglue_FT_Glyph_To_Bitmap_t)(FT_Glyph * glyph, int rendermode, FT_Vector * origin, int destroy);
112 typedef void (*cc_ftglue_FT_Done_Glyph_t)(FT_Glyph glyph);
113 typedef FT_Error (*cc_ftglue_FT_Outline_Decompose_t)(FT_Outline * outline, const FT_Outline_Funcs * func_interface, void * user);
114 typedef FT_Error (*cc_ftglue_FT_Render_Glyph_t)(void * glyphslot, int rendermode);
115 
116 typedef struct {
117   int available;
118   cc_ftglue_FT_Init_FreeType_t FT_Init_FreeType;
119   cc_ftglue_FT_Library_Version_t FT_Library_Version;
120   cc_ftglue_FT_Done_FreeType_t FT_Done_FreeType;
121   cc_ftglue_FT_New_Face_t FT_New_Face;
122   cc_ftglue_FT_Done_Face_t  FT_Done_Face;
123   cc_ftglue_FT_Select_Charmap_t FT_Select_Charmap;
124   cc_ftglue_FT_Set_Char_Size_t FT_Set_Char_Size;
125   cc_ftglue_FT_Set_Transform_t FT_Set_Transform;
126   cc_ftglue_FT_Get_Char_Index_t FT_Get_Char_Index;
127   cc_ftglue_FT_Load_Glyph_t FT_Load_Glyph;
128   cc_ftglue_FT_Get_Kerning_t FT_Get_Kerning;
129   cc_ftglue_FT_Get_Glyph_t FT_Get_Glyph;
130   cc_ftglue_FT_Glyph_To_Bitmap_t FT_Glyph_To_Bitmap;
131   cc_ftglue_FT_Done_Glyph_t FT_Done_Glyph;
132   cc_ftglue_FT_Outline_Decompose_t FT_Outline_Decompose;
133 } cc_ftglue_t;
134 
135 static cc_fcglue_t * fontconfig_instance = NULL;
136 static cc_libhandle fontconfig_libhandle = NULL;
137 static int fontconfig_failed_to_load = 0;
138 
139 static cc_ftglue_t * freetype_instance = NULL;
140 static cc_libhandle freetype_libhandle = NULL;
141 static int freetype_failed_to_load = 0;
142 
143 /* Cleans up fontconfig at exit. */
144 static void
fcglue_cleanup(void)145 fcglue_cleanup(void)
146 {
147 #ifdef FONTCONFIG_RUNTIME_LINKING
148   if (fontconfig_libhandle) {
149     cc_dl_close(fontconfig_libhandle);
150     fontconfig_libhandle = NULL;
151   }
152 #endif /* FONTCONFIG_RUNTIME_LINKING */
153   assert(fontconfig_instance);
154   free(fontconfig_instance);
155   fontconfig_instance = NULL;
156   fontconfig_failed_to_load = 0;
157 }
158 
159 static const cc_fcglue_t *
fcglue_init(void)160 fcglue_init(void)
161 {
162   CC_SYNC_BEGIN(fcglue_init);
163 
164   if (!fontconfig_instance && !fontconfig_failed_to_load) {
165     /* First invocation, do initializations. */
166     cc_fcglue_t * fi = (cc_fcglue_t *)malloc(sizeof(cc_fcglue_t));
167     (void)coin_atexit((coin_atexit_f *)fcglue_cleanup, CC_ATEXIT_DYNLIBS);
168 
169     /* The common case is that fontconfig is either available from the
170        linking process or we're successfully going to link it in. */
171     fi->available = 1;
172 
173 #ifdef FONTCONFIG_RUNTIME_LINKING
174     {
175       int idx;
176       /* FIXME: should we get the system shared library name from an
177          Autoconf check? 20000930 mortene. */
178       const char * possiblelibnames[] = {
179         NULL, /* is set below */
180         "fontconfig", "libfontconfig", "libfontconfig.so",
181         "libfontconfig.dylib",
182         NULL
183       };
184       possiblelibnames[0] = coin_getenv("COIN_FONTCONFIG_LIBNAME");
185       idx = possiblelibnames[0] ? 0 : 1;
186       while (!fontconfig_libhandle && possiblelibnames[idx]) {
187         fontconfig_libhandle = cc_dl_open(possiblelibnames[idx]);
188         idx++;
189       }
190 
191       if (!fontconfig_libhandle) {
192         fi->available = 0;
193         fontconfig_failed_to_load = 1;
194       }
195     }
196     /* Define FCGLUE_REGISTER_FUNC macro. Casting the type is
197        necessary for this file to be compatible with C++ compilers. */
198 #define FCGLUE_REGISTER_FUNC(_funcsig_, _funcname_) \
199     do { \
200       fi->_funcname_ = (_funcsig_)cc_dl_sym(fontconfig_libhandle, SO__QUOTE(_funcname_)); \
201       if (fi->_funcname_ == NULL) fi->available = 0; \
202     } while (0)
203 
204 #elif defined(FONTCONFIGGLUE_ASSUME_FONTCONFIG) /* !FONTCONFIG_RUNTIME_LINKING */
205 
206     /* Define FCGLUE_REGISTER_FUNC macro. */
207 #define FCGLUE_REGISTER_FUNC(_funcsig_, _funcname_) \
208     fi->_funcname_ = (_funcsig_)_funcname_
209 
210 #else /* !FONTCONFIGGLUE_ASSUME_FONTCONFIG */
211     fi->available = 0;
212     /* Define FCGLUE_REGISTER_FUNC macro. */
213 #define FCGLUE_REGISTER_FUNC(_funcsig_, _funcname_) \
214     fi->_funcname_ = NULL
215 
216 #endif /* !FONTCONFIGGLUE_ASSUME_FONTCONFIG */
217 
218     FCGLUE_REGISTER_FUNC(cc_fcglue_FcGetVersion_t, FcGetVersion);
219 
220     if (fi->available && (!fi->FcGetVersion)) {
221       /* something is seriously wrong */
222       cc_debugerror_post("fontconfig glue",
223                          "Loaded fontconfig DLL ok, but couldn't resolve some symbols.");
224       fi->available = 0;
225       fontconfig_failed_to_load = 1;
226       fontconfig_instance = fi;
227     }
228     else {
229       FCGLUE_REGISTER_FUNC(cc_fcglue_FcNameParse_t, FcNameParse);
230       FCGLUE_REGISTER_FUNC(cc_fcglue_FcConfigSubstitute_t, FcConfigSubstitute);
231       FCGLUE_REGISTER_FUNC(cc_fcglue_FcDefaultSubstitute_t, FcDefaultSubstitute);
232       FCGLUE_REGISTER_FUNC(cc_fcglue_FcFontMatch_t, FcFontMatch);
233       FCGLUE_REGISTER_FUNC(cc_fcglue_FcPatternGetString_t, FcPatternGetString);
234       FCGLUE_REGISTER_FUNC(cc_fcglue_FcPatternDestroy_t, FcPatternDestroy);
235       FCGLUE_REGISTER_FUNC(cc_fcglue_FcPatternPrint_t, FcPatternPrint);
236       FCGLUE_REGISTER_FUNC(cc_fcglue_FcPatternAddDouble_t, FcPatternAddDouble);
237 
238       /* Do this late, so we can detect recursive calls to this function. */
239       fontconfig_instance = fi;
240     }
241   }
242   CC_SYNC_END(fcglue_init);
243   return fontconfig_instance;
244 }
245 
246 
247 int
cc_fcglue_FcGetVersion(void)248 cc_fcglue_FcGetVersion(void)
249 {
250   assert(fontconfig_instance && fontconfig_instance->available);
251   return fontconfig_instance->FcGetVersion();
252 }
253 
254 FcPattern *
cc_fcglue_FcNameParse(const unsigned char * name)255 cc_fcglue_FcNameParse(const unsigned char * name)
256 {
257   assert(fontconfig_instance && fontconfig_instance->available);
258   return fontconfig_instance->FcNameParse(name);
259 }
260 
261 int
cc_fcglue_FcConfigSubstitute(void * config,FcPattern * pattern,FcMatchKind kind)262 cc_fcglue_FcConfigSubstitute(void * config, FcPattern * pattern, FcMatchKind kind)
263 {
264   assert(fontconfig_instance && fontconfig_instance->available);
265   return fontconfig_instance->FcConfigSubstitute(config, pattern, kind);
266 }
267 
268 void
cc_fcglue_FcDefaultSubstitute(FcPattern * pattern)269 cc_fcglue_FcDefaultSubstitute(FcPattern *pattern)
270 {
271   assert(fontconfig_instance && fontconfig_instance->available);
272   fontconfig_instance->FcDefaultSubstitute(pattern);
273 }
274 
275 FcPattern *
cc_fcglue_FcFontMatch(void * config,FcPattern * pattern,FcResult * result)276 cc_fcglue_FcFontMatch(void * config, FcPattern * pattern, FcResult * result)
277 {
278   assert(fontconfig_instance && fontconfig_instance->available);
279   return fontconfig_instance->FcFontMatch(config, pattern, result);
280 }
281 
282 FcResult
cc_fcglue_FcPatternGetString(const FcPattern * pattern,const char * object,int n,unsigned char ** s)283 cc_fcglue_FcPatternGetString(const FcPattern * pattern, const char * object, int n, unsigned char ** s)
284 {
285   assert(fontconfig_instance && fontconfig_instance->available);
286   return fontconfig_instance->FcPatternGetString(pattern, object, n, s);
287 }
288 
289 void
cc_fcglue_FcPatternDestroy(FcPattern * pattern)290 cc_fcglue_FcPatternDestroy(FcPattern * pattern)
291 {
292   assert(fontconfig_instance && fontconfig_instance->available);
293   fontconfig_instance->FcPatternDestroy(pattern);
294 }
295 
296 void
cc_fcglue_FcPatternPrint(const FcPattern * pattern)297 cc_fcglue_FcPatternPrint(const FcPattern * pattern)
298 {
299   assert(fontconfig_instance && fontconfig_instance->available);
300   fontconfig_instance->FcPatternPrint(pattern);
301 }
302 
303 int
cc_fcglue_FcPatternAddDouble(FcPattern * p,const char * object,double d)304 cc_fcglue_FcPatternAddDouble(FcPattern *p, const char *object, double d)
305 {
306   assert(fontconfig_instance && fontconfig_instance->available);
307   return fontconfig_instance->FcPatternAddDouble(p, object, d);
308 }
309 
310 int
cc_fcglue_available(void)311 cc_fcglue_available(void)
312 {
313   const char * env;
314 
315   if (!((env = coin_getenv("COIN_FORCE_FONTCONFIG_OFF")) && (atoi(env) > 0))) {
316     fcglue_init();
317   }
318   return fontconfig_instance && fontconfig_instance->available;
319 }
320 
321 
322 /* Cleans up freetype at exit. */
323 static void
ftglue_cleanup(void)324 ftglue_cleanup(void)
325 {
326 #ifdef FREETYPE_RUNTIME_LINKING
327   if (freetype_libhandle) {
328     cc_dl_close(freetype_libhandle);
329     freetype_libhandle = NULL;
330   }
331 #endif /* FREETYPE_RUNTIME_LINKING */
332   assert(freetype_instance);
333   free(freetype_instance);
334   freetype_instance = NULL;
335   freetype_failed_to_load = 0;
336 }
337 
338 static const cc_ftglue_t *
ftglue_init(void)339 ftglue_init(void)
340 {
341   CC_SYNC_BEGIN(ftglue_init);
342 
343   if (!freetype_instance && !freetype_failed_to_load) {
344     /* First invocation, do initializations. */
345     cc_ftglue_t * fi = (cc_ftglue_t *)malloc(sizeof(cc_ftglue_t));
346     (void)coin_atexit((coin_atexit_f *)ftglue_cleanup, CC_ATEXIT_DYNLIBS);
347 
348     /* The common case is that FreeType is either available from the
349        linking process or we're successfully going to link it in. */
350     fi->available = 1;
351 
352 #ifdef FREETYPE_RUNTIME_LINKING
353     {
354       int idx;
355       /* FIXME: should we get the system shared library name from an
356          Autoconf check? 20000930 mortene. */
357       const char * possiblelibnames[] = {
358         NULL, /* is set below */
359         "freetype", "libfreetype", "libfreetype.so",
360         "libfreetype.dylib",
361         NULL
362       };
363       possiblelibnames[0] = coin_getenv("COIN_FREETYPE2_LIBNAME");
364       idx = possiblelibnames[0] ? 0 : 1;
365 
366       while (!freetype_libhandle && possiblelibnames[idx]) {
367         freetype_libhandle = cc_dl_open(possiblelibnames[idx]);
368         idx++;
369       }
370 
371       if (!freetype_libhandle) {
372         fi->available = 0;
373         freetype_failed_to_load = 1;
374       }
375     }
376     /* Define FTGLUE_REGISTER_FUNC macro. Casting the type is
377        necessary for this file to be compatible with C++ compilers. */
378 #define FTGLUE_REGISTER_FUNC(_funcsig_, _funcname_) \
379     do { \
380       fi->_funcname_ = (_funcsig_)cc_dl_sym(freetype_libhandle, SO__QUOTE(_funcname_)); \
381       if (fi->_funcname_ == NULL) fi->available = 0; \
382     } while (0)
383 
384 #elif defined(FREETYPEGLUE_ASSUME_FREETYPE) /* !FREETYPE_RUNTIME_LINKING */
385 
386     /* Define FTGLUE_REGISTER_FUNC macro. */
387 #define FTGLUE_REGISTER_FUNC(_funcsig_, _funcname_) \
388     fi->_funcname_ = (_funcsig_)_funcname_
389 
390 #else /* !FREETYPEGLUE_ASSUME_FREETYPE */
391     fi->available = 0;
392     /* Define FTGLUE_REGISTER_FUNC macro. */
393 #define FTGLUE_REGISTER_FUNC(_funcsig_, _funcname_) \
394     fi->_funcname_ = NULL
395 
396 #endif /* !FREETYPEGLUE_ASSUME_FREETYPE */
397 
398     FTGLUE_REGISTER_FUNC(cc_ftglue_FT_Init_FreeType_t, FT_Init_FreeType);
399     FTGLUE_REGISTER_FUNC(cc_ftglue_FT_Library_Version_t, FT_Library_Version);
400     FTGLUE_REGISTER_FUNC(cc_ftglue_FT_Done_FreeType_t, FT_Done_FreeType);
401 
402     if (fi->available && (!fi->FT_Init_FreeType ||
403                           !fi->FT_Library_Version ||
404                           !fi->FT_Done_FreeType)) {
405       /* something is seriously wrong */
406       cc_debugerror_post("freetype glue",
407                          "Loaded freetype DLL ok, but couldn't resolve basic symbols.");
408       fi->available = 0;
409       freetype_failed_to_load = 1;
410       freetype_instance = fi;
411     }
412     else {
413       FTGLUE_REGISTER_FUNC(cc_ftglue_FT_New_Face_t, FT_New_Face);
414       FTGLUE_REGISTER_FUNC(cc_ftglue_FT_Done_Face_t, FT_Done_Face);
415       FTGLUE_REGISTER_FUNC(cc_ftglue_FT_Select_Charmap_t, FT_Select_Charmap);
416       FTGLUE_REGISTER_FUNC(cc_ftglue_FT_Set_Char_Size_t, FT_Set_Char_Size);
417       FTGLUE_REGISTER_FUNC(cc_ftglue_FT_Set_Transform_t, FT_Set_Transform);
418       FTGLUE_REGISTER_FUNC(cc_ftglue_FT_Get_Char_Index_t, FT_Get_Char_Index);
419       FTGLUE_REGISTER_FUNC(cc_ftglue_FT_Load_Glyph_t, FT_Load_Glyph);
420       FTGLUE_REGISTER_FUNC(cc_ftglue_FT_Get_Kerning_t, FT_Get_Kerning);
421       FTGLUE_REGISTER_FUNC(cc_ftglue_FT_Get_Glyph_t, FT_Get_Glyph);
422       FTGLUE_REGISTER_FUNC(cc_ftglue_FT_Glyph_To_Bitmap_t, FT_Glyph_To_Bitmap);
423       FTGLUE_REGISTER_FUNC(cc_ftglue_FT_Done_Glyph_t, FT_Done_Glyph);
424       FTGLUE_REGISTER_FUNC(cc_ftglue_FT_Outline_Decompose_t, FT_Outline_Decompose);
425 
426       /* Do this late, so we can detect recursive calls to this function. */
427       freetype_instance = fi;
428     }
429   }
430   CC_SYNC_END(ftglue_init);
431   return freetype_instance;
432 }
433 
434 
435 FT_Error
cc_ftglue_FT_Init_FreeType(FT_Library * library)436 cc_ftglue_FT_Init_FreeType(FT_Library * library)
437 {
438   assert(freetype_instance && freetype_instance->available);
439   return freetype_instance->FT_Init_FreeType(library);
440 }
441 
442 void
cc_ftglue_FT_Library_Version(void * library,int * major,int * minor,int * patch)443 cc_ftglue_FT_Library_Version(void * library, int * major, int * minor, int * patch)
444 {
445   assert(freetype_instance && freetype_instance->available);
446   freetype_instance->FT_Library_Version(library, major, minor, patch);
447 }
448 
449 void
cc_ftglue_FT_Done_FreeType(void * library)450 cc_ftglue_FT_Done_FreeType(void * library)
451 {
452   FT_Error err;
453   assert(freetype_instance && freetype_instance->available);
454   err = freetype_instance->FT_Done_FreeType(library);
455   assert(err == 0 && "something bad happened at FreeType exit");
456 }
457 
458 FT_Error
cc_ftglue_FT_New_Face(void * library,const char * filepathname,long faceindex,FT_Face * face)459 cc_ftglue_FT_New_Face(void * library, const char * filepathname, long faceindex, FT_Face * face)
460 {
461   assert(freetype_instance && freetype_instance->available);
462   return freetype_instance->FT_New_Face(library, filepathname, faceindex, face);
463 }
464 
465 FT_Error
cc_ftglue_FT_Done_Face(void * face)466 cc_ftglue_FT_Done_Face(void * face)
467 {
468   assert(freetype_instance && freetype_instance->available);
469   return freetype_instance->FT_Done_Face(face);
470 }
471 
472 FT_Error
cc_ftglue_FT_Select_Charmap(FT_Face face,int encoding)473 cc_ftglue_FT_Select_Charmap(FT_Face face, int encoding)
474 {
475   assert(freetype_instance && freetype_instance->available);
476   return freetype_instance->FT_Select_Charmap(face, encoding);
477 }
478 
479 FT_Error
cc_ftglue_FT_Set_Char_Size(FT_Face face,long width,long height,unsigned int hres,unsigned int vres)480 cc_ftglue_FT_Set_Char_Size(FT_Face face, long width, long height, unsigned int hres, unsigned int vres)
481 {
482   assert(freetype_instance && freetype_instance->available);
483   return freetype_instance->FT_Set_Char_Size(face, width, height, hres, vres);
484 }
485 
486 void
cc_ftglue_FT_Set_Transform(FT_Face face,FT_Matrix * matrix,FT_Vector * delta)487 cc_ftglue_FT_Set_Transform(FT_Face face, FT_Matrix * matrix, FT_Vector * delta)
488 {
489   assert(freetype_instance && freetype_instance->available);
490   freetype_instance->FT_Set_Transform(face, matrix, delta);
491 }
492 
493 FT_UInt
cc_ftglue_FT_Get_Char_Index(FT_Face face,unsigned long charidx)494 cc_ftglue_FT_Get_Char_Index(FT_Face face, unsigned long charidx)
495 {
496   assert(freetype_instance && freetype_instance->available);
497   return freetype_instance->FT_Get_Char_Index(face, charidx);
498 }
499 
500 FT_Error
cc_ftglue_FT_Load_Glyph(FT_Face face,unsigned int glyph,int32_t loadflags)501 cc_ftglue_FT_Load_Glyph(FT_Face face, unsigned int glyph, int32_t loadflags)
502 {
503   assert(freetype_instance && freetype_instance->available);
504   return freetype_instance->FT_Load_Glyph(face, glyph, loadflags);
505 }
506 
507 FT_Error
cc_ftglue_FT_Get_Kerning(FT_Face face,unsigned int left,unsigned int right,unsigned int kernmode,FT_Vector * akerning)508 cc_ftglue_FT_Get_Kerning(FT_Face face, unsigned int left, unsigned int right, unsigned int kernmode, FT_Vector * akerning)
509 {
510   assert(freetype_instance && freetype_instance->available);
511   return freetype_instance->FT_Get_Kerning(face, left, right, kernmode, akerning);
512 }
513 
514 FT_Error
cc_ftglue_FT_Get_Glyph(void * glyphslot,FT_Glyph * glyph)515 cc_ftglue_FT_Get_Glyph(void * glyphslot, FT_Glyph * glyph)
516 {
517   assert(freetype_instance && freetype_instance->available);
518   return freetype_instance->FT_Get_Glyph(glyphslot, glyph);
519 }
520 
521 FT_Error
cc_ftglue_FT_Glyph_To_Bitmap(FT_Glyph * glyph,int rendermode,FT_Vector * origin,int destroy)522 cc_ftglue_FT_Glyph_To_Bitmap(FT_Glyph * glyph, int rendermode, FT_Vector * origin, int destroy)
523 {
524   assert(freetype_instance && freetype_instance->available);
525   return freetype_instance->FT_Glyph_To_Bitmap(glyph, rendermode, origin, destroy);
526 }
527 
528 void
cc_ftglue_FT_Done_Glyph(FT_Glyph glyph)529 cc_ftglue_FT_Done_Glyph(FT_Glyph glyph)
530 {
531   assert(freetype_instance && freetype_instance->available);
532   freetype_instance->FT_Done_Glyph(glyph);
533 }
534 
535 int
cc_ftglue_available(void)536 cc_ftglue_available(void)
537 {
538   ftglue_init();
539   return freetype_instance && freetype_instance->available;
540 }
541 
542 FT_Error
cc_ftglue_FT_Outline_Decompose(FT_Outline * outline,const FT_Outline_Funcs * func_interface,void * user)543 cc_ftglue_FT_Outline_Decompose(FT_Outline * outline, const FT_Outline_Funcs * func_interface, void * user)
544 {
545   assert(freetype_instance && freetype_instance->available);
546   return freetype_instance->FT_Outline_Decompose(outline, func_interface, user);
547 }
548