Commit a67fecb
Fix code for loading TTF and OTF fonts
Changed files (10)
modifiedbuild.pymodifieddodo.pymodifiedlibbirdfont/Font.valamodifiedlibbirdfont/OpenFontFormat/OpenFontFormatReader.valamodifiedlibbirdfont/OpenFontFormat/load_font.caddedlibbirdfont/OpenFontFormat/loadfont.hmodifiedlibbirdfont/Renderer/FallbackFont.valamodifiedlibbirdfont/Renderer/fontconfig.cmodifiedlibbirdfont/TestCases.valaaddedloadfont.vapi
Diff
@@ -11,7 +11,6 @@ from scripts import version if platform == 'msys': process_tasks(dodo.make_libbirdgems('libbirdgems.dll', [])) process_tasks(dodo.make_libbirdfont('libbirdfont.dll', ['libbirdgems.dll']))- process_tasks(dodo.make_birdfont_test('birdfont-test.exe', ['libbirdgems.so', 'libbirdfont.so'])) elif platform == 'darwin': gems = "libbirdgems." + str(version.LIBBIRDGEMS_SO_VERSION) + '.dylib' bird = "libbirdfont." + str(version.SO_VERSION) + '.dylib';@@ -21,7 +20,6 @@ elif platform == 'darwin': else: process_tasks(dodo.task_libbirdgems()) process_tasks(dodo.task_libbirdfont())- process_tasks(dodo.make_birdfont_test('birdfont-test', ['libbirdgems.so', 'libbirdfont.so'])) process_tasks(dodo.task_birdfont()) process_tasks(dodo.task_birdfont_autotrace())@@ -35,8 +35,7 @@ DOIT_CONFIG = { 'birdfont', 'birdfont-autotrace', 'birdfont-export',- 'birdfont-import',- 'birdfont-test'+ 'birdfont-import' ], } @@ -189,6 +188,7 @@ def make_birdfont_import(target_binary, deps): {valacflags[birdfont-import]} \ birdfont-import/*.vala \ --vapidir=./ \+ loadfont.vapi \ --pkg {gee} \ --pkg gio-2.0 \ --pkg cairo \@@ -292,29 +292,30 @@ def make_birdfont_autotrace(target_binary, deps): def task_birdfont_autotrace(): yield make_birdfont_autotrace('birdfont-autotrace', ['libbirdgems.so', 'libbirdfont.so']) -def make_libbirdfont(target_binary, deps):- valac_command = """{valac} \+def make_libbirdfont(target_binary, deps): + valac_command = config.VALAC + """\ -C \ --vapidir=./ \ --basedir build/libbirdfont/ \- {non_null} \- {valacflags[libbirdfont]} \+ """ + config.NON_NULL + """ \+ """ + config.VALACFLAGS.get("libbirdfont", "") + """ \ --enable-experimental \ --library libbirdfont \ -H build/libbirdfont/birdfont.h \ libbirdfont/*.vala \ libbirdfont/OpenFontFormat/*.vala \ libbirdfont/Renderer/*.vala \+ loadfont.vapi \ --pkg posix \- --pkg {gee} \+ --pkg """ + config.GEE + """ \ --pkg gio-2.0 \ --pkg cairo \ --pkg xmlbird \ --pkg libbirdgems \ --pkg sqlite3 \ --pkg gdk-pixbuf-2.0 \- """.format(**config.SETTINGS)-+ """+ cc_command = """{cc} {cflags[libbirdfont]} \ -c C_SOURCE \ -fPIC \@@ -438,58 +439,3 @@ def task_build (): return { 'actions': ['echo "Build"'], }--def make_birdfont_test(target_binary, deps):- valac_command = """{valac} \- -C \- --vapidir=./ \- --basedir build/birdfont-test/ \- {non_null} \- {valacflags[birdfont-test]} \- --enable-experimental \- birdfont-test/*.vala \- --vapidir=./ \- --pkg {gee} \- --pkg gio-2.0 \- --pkg cairo \- --pkg xmlbird \- --pkg libbirdfont \- """.format(**config.SETTINGS)-- cc_command = """{cc} {cflags[birdfont-test]} \- -c C_SOURCE \- -D 'GETTEXT_PACKAGE="birdfont"' \- -I./build/libbirdfont \- $({pkg-config} --cflags sqlite3) \- $({pkg-config} --cflags {gee}) \- $({pkg-config} --cflags gio-2.0) \- $({pkg-config} --cflags cairo) \- $({pkg-config} --cflags glib-2.0) \- $({pkg-config} --cflags xmlbird) \- -o OBJECT_FILE""".format(**config.SETTINGS)-- linker_command = """{cc} {ldflags[birdfont-test]} \- build/birdfont-test/*.o \- -L./build/bin -lbirdfont \- $({pkg-config} --libs sqlite3) \- $({pkg-config} --libs {gee}) \- $({pkg-config} --libs gio-2.0) \- $({pkg-config} --libs cairo) \- $({pkg-config} --libs cairo-gobject) \- $({pkg-config} --libs glib-2.0) \- $({pkg-config} --libs xmlbird) \- -L./build -L./build/bin -l birdgems \- -o build/bin/""".format(**config.SETTINGS) + target_binary-- test = Builder('birdfont-test',- valac_command, - cc_command,- linker_command,- target_binary,- None,- deps)- - yield test.build()--def task_birdfont_test():- yield make_birdfont_test('birdfont-test', ['libbirdgems.so', 'libbirdfont.so'])@@ -1040,7 +1040,7 @@ public class Font : GLib.Object { bool parsed; BirdFontFile bf_font = new BirdFontFile (this); - data = load_freetype_font (path, out error);+ data = LoadFont.load_freetype_font (path, out error); if (error != 0) { warning ("Failed to load freetype font.");@@ -17,21 +17,6 @@ public extern class FontFace { } -[CCode (cname = "load_freetype_font")]-public extern static StringBuilder? load_freetype_font (string file, out int error);--[CCode (cname = "validate_freetype_font")]-public extern static bool validate_freetype_font (string file);--[CCode (cname = "load_glyph")]-public extern static StringBuilder? load_glyph (FontFace font, uint unicode);--[CCode (cname = "open_font")]-public extern static FontFace* open_font (string font_file);--[CCode (cname = "close_ft_font")]-public extern static void close_font (FontFace* font);- namespace BirdFont { [SimpleType]@@ -1,17 +1,11 @@ /*- Copyright (C) 2013 2014 2015 2018 Johan Mattsson+ Copyright (C) 2013 2014 2015 2019 Johan Mattsson - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 3 of the - License, or (at your option) any later version.-- This library is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details.+ All rights reserved. */ +#include "loadfont.h"+ #include <assert.h> #include <glib.h> #include <stdio.h>@@ -23,7 +17,6 @@ #include FT_OPENTYPE_VALIDATE_H #include FT_TRUETYPE_TABLES_H #include FT_SFNT_NAMES_H- #include "birdfont.h" /** Error codes. */@@ -36,12 +29,7 @@ #define DOUBLE_CURVE 4 #define HIDDEN_CURVE 8 -typedef struct FontFace {- FT_Face face;- FT_Library library;-} FontFace;--void close_ft_font (FontFace* font);+extern GString* load_freetype_font (const gchar* file, gint* err); /** Convert units per em in font file format to the BirdFont format. */ double get_units (double units_per_em) {@@ -216,7 +204,7 @@ void create_contour (guint unicode, FT_Vector* points, char* flags, int* length, prev_is_curve = FALSE; f[j] = CUBIC_CURVE; } else {- g_warning ("WARNING invalid point flags: %d index: %d.\n", flags[i], i);+ g_warning ("invalid point flags: %d index: %d.\n", flags[i], i); prev_is_curve = FALSE; f[j] = ON_CURVE; }@@ -394,14 +382,27 @@ GString* get_bf_contour_data (guint unicode, FT_Vector* points, char* flags, int double units = get_units (units_per_em); guint prev_is_curve; int points_length;+ gboolean cnc_open = FALSE;+ if (length == 0) { return bf; } points_length = length;++ gboolean last_to_first = FALSE;+ + int last_x = 0;+ int last_y = 0;+ create_contour (unicode, points, flags, &length, &new_points, &new_flags, err); + if (length < 2) {+ g_warning ("No contour.");+ return bf;+ }+ x0 = new_points[0].x * units; y0 = new_points[0].y * units; @@ -455,6 +456,9 @@ GString* get_bf_contour_data (guint unicode, FT_Vector* points, char* flags, int g_ascii_formatd (coordinate, 80, "%f", y2); g_string_append (contour, coordinate); + last_x = new_points[i+2].x;+ last_y = new_points[i+2].y;+ i += 3; } else if (is_double_curve (new_flags[i])) { x0 = new_points[i].x * units;@@ -488,6 +492,9 @@ GString* get_bf_contour_data (guint unicode, FT_Vector* points, char* flags, int g_ascii_formatd (coordinate, 80, "%f", y2); g_string_append (contour, coordinate);++ last_x = new_points[i+2].x;+ last_y = new_points[i+2].y; i += 3; } else if (is_quadratic (new_flags[i])) {@@ -513,6 +520,9 @@ GString* get_bf_contour_data (guint unicode, FT_Vector* points, char* flags, int g_ascii_formatd (coordinate, 80, "%f", y1); g_string_append (contour, coordinate); + last_x = new_points[i + 1].x;+ last_y = new_points[i + 1].y;+ i += 2; } else if (is_line (new_flags[i])) { x0 = new_points[i].x * units;@@ -528,9 +538,12 @@ GString* get_bf_contour_data (guint unicode, FT_Vector* points, char* flags, int g_string_append (contour, coordinate); i += 1;+ + last_x = new_points[i].x;+ last_y = new_points[i].y; } else { contour = g_string_new ("");- g_warning ("WARNING Can't parse outline.\n");+ g_warning ("Can't parse outline.\n"); *err = 1; i++; }@@ -538,6 +551,14 @@ GString* get_bf_contour_data (guint unicode, FT_Vector* points, char* flags, int g_string_append (bf, contour->str); g_string_free (contour, TRUE); }++ if (length > 0) {+ last_to_first = (last_x == new_points[0].x && last_y == new_points[0].y); + + if (cnc_open && !last_to_first) {+ g_string_append (bf, " O");+ }+ } free (new_points); free (new_flags);@@ -570,29 +591,36 @@ GString* get_bf_path (guint unicode, FT_Face face, double units_per_em, int* err return bf; } -FontFace* open_font (const char* file) {+FreeTypeFontFace* open_font (const gchar* file) { FT_Library library = NULL; FT_Face face = NULL; int error;- FontFace* font;+ FreeTypeFontFace* font; error = FT_Init_FreeType (&library); if (error != OK) {- printf ("Freetype init error %d.\n", error);+ g_warning ("Freetype init error %d.\n", error); return NULL; } - error = FT_New_Face (library, file, 0, &face);+ gchar* short_path = file;++ error = FT_New_Face (library, short_path, 0, &face);+ if (error) { if (FT_Done_FreeType (library) != 0) { g_warning ("Can't close freetype."); } - g_warning ("Freetype font face error %d\n", error);+ g_warning ("Freetype font face error %d in (open_font)", error);+ g_warning ("Can't open file %s", file);+ g_warning ("Short path: %s", short_path);+ return NULL;+ } - font = malloc (sizeof (FontFace));+ font = malloc (sizeof (FreeTypeFontFace)); font->face = face; font->library = library; @@ -606,7 +634,7 @@ FontFace* open_font (const char* file) { return font; } -void close_ft_font (FontFace* font) {+void close_ft_font (FreeTypeFontFace* font) { if (font != NULL) { if (font->face != NULL) { if (FT_Done_Face (font->face) != 0) {@@ -626,7 +654,7 @@ void close_ft_font (FontFace* font) { } } -GString* load_glyph (FontFace* font, guint unicode) {+GString* load_glyph (FreeTypeFontFace* font, guint unicode) { GString* glyph; GString* paths; int err = OK;@@ -638,7 +666,7 @@ GString* load_glyph (FontFace* font, guint unicode) { FT_Error error; if (font == NULL || font->face == NULL || font->library == NULL) {- printf ("WARNING No font in load_glyph");+ g_warning ("No font in load_glyph"); return NULL; } @@ -667,7 +695,7 @@ GString* load_glyph (FontFace* font, guint unicode) { error = FT_Load_Glyph(font->face, gid, FT_LOAD_DEFAULT | FT_LOAD_NO_SCALE); if (error != 0) {- printf ("WARNING Failed to load glyph.");+ g_warning ("Failed to load glyph."); g_string_free (glyph, TRUE); return NULL; }@@ -675,7 +703,7 @@ GString* load_glyph (FontFace* font, guint unicode) { paths = get_bf_path (unicode, font->face, font->face->units_per_EM, &err); if (err != OK) {- printf ("WARNING Can't load glyph.");+ g_warning ("Can't load glyph."); g_string_free (glyph, TRUE); g_string_free (paths, TRUE); return NULL;@@ -1059,41 +1087,73 @@ GString* get_bf_font (FT_Face face, char* file, int* err) { FT_ULong* charcodes = get_charcodes (face, i); int charcode_index = 0;+ gboolean has_unicode_value;+ guint unassigned_index = 0; while (TRUE) { charcode = charcodes[charcode_index]; if (charcode == 0) {- free (charcodes);- charcodes = NULL;- break;+ has_unicode_value = FALSE;+ } else {+ has_unicode_value = TRUE;+ }+ + if (charcode < 32) { // control character+ g_warning ("Control character found, %d.", (guint)charcode);+ has_unicode_value = FALSE; } glyph = g_string_new (""); - if (charcode > 32) { // not control character- g_string_append_printf (glyph, "<collection unicode=\"U+%x\">\n", (guint)charcode);- g_string_append_printf (glyph, "\t<glyph left=\"%f\" right=\"%f\" selected=\"true\">\n", 0.0, face->glyph->metrics.horiAdvance * units);- - bf_data = get_bf_path (charcode, face, units_per_em, err);- g_string_append (glyph, bf_data->str); - - g_string_append (glyph, "\t</glyph>\n");- g_string_append_printf (glyph, "</collection>\n");+ if (charcode == 32) { // import space later+ break;+ }+ + if (!has_unicode_value) {+ g_warning ("Ignoring glyph without a Unicode value, %d. (condition: %d)", + i, has_unicode_value);+ break;+ }+ + g_string_append_printf (glyph, "<collection ");+ + if (has_unicode_value) {+ g_string_append_printf (glyph, "unicode=\"U+%x\"", (guint)charcode); } else {- g_warning ("Ignoring control character, %d.", (guint)charcode);+ if (i == 0) {+ g_string_append_printf (glyph, "name=\".notdef\"");+ } else {+ unassigned_index++;+ g_string_append_printf (glyph, "name=\"unassigned_character_%d\"", unassigned_index);+ } }+ + g_string_append_printf (glyph, ">\n");+ + g_string_append_printf (glyph, "\t<glyph left=\"%f\" right=\"%f\" selected=\"true\">\n", 0.0, face->glyph->metrics.horiAdvance * units);+ + bf_data = get_bf_path (charcode, face, units_per_em, err);+ g_string_append (glyph, bf_data->str); + + g_string_append (glyph, "\t</glyph>\n");+ g_string_append_printf (glyph, "</collection>\n"); g_string_append (bf, glyph->str); g_string_free (glyph, TRUE); charcode_index++;+ + if (!has_unicode_value) {+ break;+ } } } bird_font_open_font_format_reader_append_kerning (bf, file); g_string_append (bf, "</font>\n");+ return bf; }@@ -1101,8 +1161,9 @@ GString* get_bf_font (FT_Face face, char* file, int* err) { /** Load typeface with freetype2 and return the result as a bf font. * Parameter err will be set to non zero vaule if an error occurs. */-GString* load_freetype_font (char* file, int* err) {- GString* bf = NULL;+GString* load_freetype_font (const gchar* file, gint* err) {+ GString* bf = g_string_new ("");+ GString* bf_data = g_string_new (""); FT_Library library; FT_Face face;@@ -1116,10 +1177,33 @@ GString* load_freetype_font (char* file, int* err) { *err = error; return bf; }+ + if (file == NULL) {+ g_warning ("No file provided for freetype.");+ *err = 1;+ return bf;+ }+ + // What on earth is happening when I return strings from vala land to the c domain?+ // The result is that the application craches and the data seems to be corrupted+ // but why, WHY?+ //+ // I can't answer this question. Simply passing a buffer and letting the vala method+ // fill it with data works. Minimal test code doesn't crash. There is a dog burried+ // somewhere here.+ //+ // Upadte: it was probably a problem with the header file, it has been fixed. I have+ // not tested the new code.+ + gchar* short_path = calloc ((2048 + 1), sizeof(gchar));+ short_path = file; - error = FT_New_Face (library, file, 0, &face);+ error = FT_New_Face (library, short_path, 0, &face); if (error) {- g_warning ("Freetype font face error %d\n", error);+ g_warning ("Freetype font face error %d in (load_freetype_font)", error);+ g_warning ("Can't open file %s", file);+ g_warning ("Short path: %s", short_path);+ *err = error; return bf; }@@ -1138,17 +1222,163 @@ GString* load_freetype_font (char* file, int* err) { return bf; } - bf = get_bf_font (face, file, &error);+ bf_data = get_bf_font (face, file, &error);+ if (error != OK) { g_warning ("Failed to parse font.\n"); *err = error; return bf; } - FT_Done_Face ( face );- FT_Done_FreeType( library );+ FT_Done_Face (face);+ FT_Done_FreeType (library); *err = OK;+ g_string_append (bf, bf_data->str);+ return bf; } +gboolean freetype_has_glyph (FreeTypeFontFace* font, guint unicode) {+ if (font == NULL || font->face == NULL || font->library == NULL) {+ g_warning ("No font in freetype_has_glyph");+ return FALSE;+ }++ int gid = FT_Get_Char_Index (font->face, unicode);+ + return gid != 0;+}++gboolean get_freetype_font_is_regular (const char* file) {+ FT_Library library = NULL;+ FT_Face face = NULL;+ int error;+ FreeTypeFontFace* font;+ + error = FT_Init_FreeType (&library);+ + if (error != OK) {+ g_warning ("Freetype init error %d.\n", error);+ return NULL;+ }++ gchar* short_path = calloc ((2048 + 1), sizeof(gchar));+ short_path = g_strdup (file);++ error = FT_New_Face (library, short_path, 0, &face);+ + if (error) {+ if (FT_Done_FreeType (library) != 0) {+ g_warning ("Can't close freetype.");+ }+ + g_warning ("Freetype font face error %d in (open_font)", error);+ g_warning ("Can't open file %s", file);+ g_warning ("Short path: %s", short_path);+ + return NULL;+ }+ + if (font == NULL || font->face == NULL || font->library == NULL) {+ g_warning ("No font in get_freetype_font_is_regular");+ return FALSE;+ }+ + return !g_str_match_string ("Bold", face->style_name, FALSE)+ && !g_str_match_string ("Italic", face->style_name, FALSE);+}++gulong* get_all_unicode_points_in_font (const gchar* file) {+ FT_ULong* charcodes = NULL;+ FT_Library library;+ FT_Face face;++ int error = FT_Init_FreeType (&library);+ + if (error != OK) {+ g_warning ("Freetype init error %d.\n", error);+ return NULL;+ }+ + if (file == NULL) {+ g_warning ("No file provided for freetype.");+ return NULL;+ }+ + gchar* short_path = g_strdup (file);+ + error = FT_New_Face (library, short_path, 0, &face);+ if (error) {+ g_warning ("Freetype font face error %d in (load_freetype_font)", error);+ g_warning ("Can't open file %s", file);+ g_warning ("Short path: %s", short_path);+ return NULL;+ }++ error = FT_Select_Charmap (face , FT_ENCODING_UNICODE);+ if (error) {+ g_warning ("Freetype can not use Unicode, error: %d\n", error);+ return NULL;+ }++ if (face == NULL) {+ g_warning("No font face in get_all_unicode_points_in_font");+ return NULL;+ }+ + if (face->num_glyphs == 0) {+ return NULL;+ }+ + gboolean error_in_result = FALSE;+ gint gindex = 0;+ FT_ULong charcode;+ gint num_glyphs = 0;+ + // cound how big the result buffer needs to be+ charcode = FT_Get_First_Char (face, &gindex);+ + for (int i = 0; i < face->num_glyphs && !error; i++) {+ while (gindex != 0) {+ charcode = FT_Get_Next_Char (face, charcode, &gindex);+ num_glyphs++; + }+ }++ // Fill the result buffer+ + gulong* result = malloc((num_glyphs + 1) * sizeof (gulong));+ int result_index = 0;+ + if (result == NULL) {+ g_warning ("cant malloc result buffer of size %d ", num_glyphs);+ return NULL;+ }+ + charcode = FT_Get_First_Char (face, &gindex);+ + for (int i = 0; i < num_glyphs && !error_in_result && gindex > 0; i++) {+ while (gindex != 0) {+ charcode = FT_Get_Next_Char (face, charcode, &gindex);+ + if (charcode != 0) {+ if (result_index < 0 || result_index > num_glyphs) {+ error_in_result = TRUE;+ g_warning ("result_index out of bounds %d", result_index);+ break;+ }+ + result[result_index] = charcode;+ result_index++;+ }+ }+ }++ result[result_index] = 0;+ + FT_Done_Face (face);+ FT_Done_FreeType (library);+ + return result;+}\ No newline at end of filenew file mode 100644@@ -0,0 +1,27 @@+#include <glib.h>+#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_GLYPH_H+#include FT_OPENTYPE_VALIDATE_H+#include FT_TRUETYPE_TABLES_H+#include FT_SFNT_NAMES_H++#ifndef LOADFONT_H+#define LOADFONT_H 1++typedef struct FreeTypeFontFace {+ FT_Face face;+ FT_Library library;+} FreeTypeFontFace;++void close_ft_font (FreeTypeFontFace* font);++GString* load_glyph (FreeTypeFontFace* font, guint unicode);+GString* load_freetype_font (const gchar* file, int* err);++FreeTypeFontFace* open_font (const gchar* file);++gulong* get_all_unicode_points_in_font (const gchar* file);+gboolean freetype_has_glyph (FreeTypeFontFace* font, guint unicode);+gboolean get_freetype_font_is_regular (const char* file);+#endif\ No newline at end of file@@ -55,7 +55,7 @@ namespace BirdFont { public class FallbackFont : GLib.Object { Gee.ArrayList<File> font_directories; - FontFace* default_font = null;+ LoadFont.FreeTypeFontFace* default_font = null; public static FcConfig* font_config = null; static bool font_config_started = false; @@ -104,7 +104,7 @@ public class FallbackFont : GLib.Object { ~FallbackFont () { if (default_font != null) {- close_font (default_font);+ LoadFont.close_font (default_font); } } @@ -190,7 +190,7 @@ public class FallbackFont : GLib.Object { BirdFontFile bf_parser; Font bf_font; StringBuilder? glyph_data;- FontFace* font;+ LoadFont.FreeTypeFontFace* font; bf_font = new Font (); font_file = null;@@ -215,9 +215,9 @@ public class FallbackFont : GLib.Object { if (glyph_data == null) { font_file = find_font (font_config, (!) c.to_string ()); if (font_file != null) {- font = open_font ((!) font_file);+ font = LoadFont.open_font ((!) font_file); glyph_data = get_glyph_in_font (font, c);- close_font (font);+ LoadFont.close_font (font); } } @@ -229,12 +229,12 @@ public class FallbackFont : GLib.Object { return bf_font; } - public StringBuilder? get_glyph_in_font (FontFace* font, unichar c) {+ internal StringBuilder? get_glyph_in_font (LoadFont.FreeTypeFontFace* font, unichar c) { StringBuilder? glyph_data = null; GlyphCollection gc; gc = new GlyphCollection (c, (!)c.to_string ()); - glyph_data = load_glyph (font, (uint) c);+ glyph_data = LoadFont.load_glyph (font, (uint) c); return glyph_data; }@@ -317,7 +317,7 @@ public class FallbackFont : GLib.Object { string? fn = get_default_font_file (); if (fn != null) {- default_font = open_font ((!) fn);+ default_font = LoadFont.open_font ((!) fn); } } @@ -13,7 +13,7 @@ */ #include <stdio.h>-#include <glib.h>+#include <glib.h>a #include <fontconfig/fontconfig.h> gchar* find_font_with_property (FcConfig* fontconfig, const gchar* characters, const gchar* property) {@@ -202,7 +202,7 @@ class TestCases { warning ("File does not exist."); } - data = load_freetype_font ((!) f.get_path (), out error);+ data = LoadFont.load_freetype_font ((!) f.get_path (), out error); if (error != 0) { warning ("Failed to load font."); return;new file mode 100644@@ -0,0 +1,31 @@+namespace LoadFont {+ +[CCode (cname = "FreeTypeFontFace", cheader_filename="loadfont.h")]+public extern class FreeTypeFontFace {+}++[CCode (cname = "load_freetype_font", cheader_filename="loadfont.h")]+public extern static GLib.StringBuilder? load_freetype_font (string file, out int error);++[CCode (cname = "validate_freetype_font", cheader_filename="loadfont.h")]+public extern static bool validate_freetype_font (string file);++[CCode (cname = "load_glyph", cheader_filename="loadfont.h")]+public extern static GLib.StringBuilder? load_glyph (FreeTypeFontFace font, uint unicode);++[CCode (cname = "open_font", cheader_filename="loadfont.h")]+public extern static FreeTypeFontFace* open_font (string font_file);++[CCode (cname = "freetype_has_glyph", cheader_filename="loadfont.h")]+public extern static bool freetype_has_glyph (FreeTypeFontFace font, uint unicode);++[CCode (cname = "close_ft_font", cheader_filename="loadfont.h")]+public extern static void close_font (FreeTypeFontFace* font);++[CCode (cname = "get_all_unicode_points_in_font", cheader_filename="loadfont.h")]+public extern static ulong* get_all_unicode_points_in_font (string file);++[CCode (cname = "get_freetype_font_is_regular", cheader_filename="loadfont.h")]+public extern static bool get_freetype_font_is_regular (string file);++}