The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

FallbackFont.vala in libbirdfont/Renderer

This file is a part of the Birdfont project.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git

Revisions

View the latest version of libbirdfont/Renderer/FallbackFont.vala.
Fix memory leak
1 /* 2 Copyright (C) 2015 Johan Mattsson 3 4 This library is free software; you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 3 of the 7 License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 */ 14 15 using Gee; 16 using Sqlite; 17 using Bird; 18 19 namespace BirdFont { 20 21 public class FallbackFont : GLib.Object { 22 static unowned Database db; 23 static Database? database = null; 24 25 Gee.ArrayList<File> fallback_fonts; 26 Gee.ArrayList<File> font_directories; 27 28 public FallbackFont () { 29 string home = Environment.get_home_dir (); 30 31 fallback_fonts = new Gee.ArrayList<File> (); 32 font_directories = new Gee.ArrayList<File> (); 33 34 add_font_folder ("/usr/share/fonts/"); 35 add_font_folder ("/usr/local/share/fonts/"); 36 add_font_folder (home + "/.local/share/fonts"); 37 add_font_folder ("C:\\Windows\\Fonts"); 38 39 //FIXME: MAC 40 41 open_fallback_fonts (); 42 } 43 44 void open_fallback_fonts () { 45 add_font ("times.ttf"); 46 add_font ("arial.ttf"); 47 add_font ("verdana.ttf"); 48 add_font ("calibri.ttf"); 49 50 add_font ("Ubuntu-R.ttf"); 51 52 add_font ("DroidKufi.ttf"); 53 add_font ("DroidSansGeorgian.ttf"); 54 add_font ("DroidSansHebrew.ttf"); 55 add_font ("DroidNaskh.ttf"); 56 add_font ("DroidSansJapanese.ttf"); 57 add_font ("DroidSansArabic.ttf"); 58 add_font ("DroidSansArmenian.ttf"); 59 add_font ("DroidSans.ttf"); 60 add_font ("DroidSansEthiopic.ttf"); 61 add_font ("DroidSansFallbackFull.ttf"); 62 63 add_font ("Roboto-Regular.ttf"); 64 } 65 66 void add_font (string font) { 67 File f = find_font_file (font); 68 69 if (f.query_exists ()) { 70 fallback_fonts.add (f); 71 } 72 } 73 74 File find_font_file (string font_file) { 75 File d, f; 76 77 for (int i = font_directories.size - 1; i >= 0; i--) { 78 d = font_directories.get (i); 79 f = get_child (d, font_file); 80 81 if (f.query_exists ()) { 82 return f; 83 } 84 } 85 86 return File.new_for_path (font_file); 87 } 88 89 void add_font_folder (string f) { 90 File folder = File.new_for_path (f); 91 FileInfo? file_info; 92 string fn; 93 94 try { 95 if (folder.query_exists ()) { 96 font_directories.add (folder); 97 98 var enumerator = folder.enumerate_children (FileAttribute.STANDARD_NAME + "," + FileAttribute.STANDARD_TYPE, 0); 99 100 while ((file_info = enumerator.next_file ()) != null) { 101 fn = ((!) file_info).get_name (); 102 103 if (((!)file_info).get_file_type () == FileType.DIRECTORY) { 104 add_font_folder ((!) get_child (folder, fn).get_path ()); 105 } 106 } 107 } 108 } catch (GLib.Error e) { 109 warning (e.message); 110 } 111 } 112 113 public Font get_single_glyph_font (unichar c) { 114 Font f = load_glyph_from_ttf (c); 115 return f; 116 } 117 118 public Font load_glyph_from_ttf (unichar c) { 119 Font? bf_font; 120 File f; 121 FontFace* font; 122 123 bf_font = new Font (); 124 125 for (int i = fallback_fonts.size - 1; i >= 0; i--) { 126 f = fallback_fonts.get (i); 127 128 font = open_font ((!) f.get_path ()); 129 bf_font = get_glyph_in_font ((!) font, c); 130 131 close_font (font); 132 133 if (bf_font != null) { 134 return (!) bf_font; 135 } 136 } 137 138 return bf_font != null ? (!) bf_font : new Font (); 139 } 140 141 public Font? get_glyph_in_font (FontFace font, unichar c) { 142 StringBuilder? glyph_data = null; 143 GlyphCollection gc; 144 BirdFontFile bf_parser; 145 Font bf_font = new Font (); 146 147 gc = new GlyphCollection (c, (!)c.to_string ()); 148 glyph_data = load_glyph (font, (uint) c); 149 150 if (glyph_data == null) { 151 return null; 152 } 153 154 bf_parser = new BirdFontFile (bf_font); 155 bf_parser.load_data (((!) glyph_data).str); 156 157 return bf_font; 158 } 159 160 public File get_database_file () { 161 return SearchPaths.find_file (null, "fallback-font.sqlite"); 162 } 163 164 public File get_new_database_file () { 165 string? fn = BirdFont.get_argument ("--fallback-font"); 166 167 if (fn != null && ((!) fn) != "") { 168 return File.new_for_path ((!) fn); 169 } 170 171 return File.new_for_path ("fallback-font.sqlite"); 172 } 173 174 public void generate_fallback_font () { 175 File f = get_new_database_file (); 176 string? fonts = BirdFont.get_argument ("--fonts"); 177 string fallback; 178 179 if (fonts == null) { 180 stderr.printf ("Add a list of fonts to use as fallback to the \"--fonts\" argument.\n"); 181 stderr.printf ("Separate each font file with \":\"\n"); 182 return; 183 } 184 185 fallback = (!) fonts; 186 187 stdout.printf ("Generating fallback font: %s\n", (!) f.get_path ()); 188 189 try { 190 if (f.query_exists ()) { 191 f.delete (); 192 } 193 194 open_database (f); 195 create_tables (); 196 197 foreach (string font in fallback.split (":")) { 198 add_font (font); 199 } 200 } catch (GLib.Error e) { 201 warning (e.message); 202 } 203 204 } 205 206 /* //FIXME:DELETE 207 public void add_font (string font_file) { 208 Font font; 209 Glyph g; 210 BirdFontFile bf; 211 File single_glyph_font; 212 213 font = new Font (); 214 single_glyph_font = File.new_for_path ("/tmp/fallback_glyph.bf"); 215 216 font.set_file (font_file); 217 if (!font.load ()) { 218 stderr.printf ("Failed to load font: " + font_file); 219 return; 220 } 221 222 for (int i = 0; i < font.length (); i++) { 223 g = (!) font.get_glyph_indice (i); 224 bf = new BirdFontFile (font); 225 } 226 } */ 227 228 public void open_database (File db_file) { 229 int rc = Database.open ((!) db_file.get_path (), out database); 230 231 db = (!) database; 232 233 if (rc != Sqlite.OK) { 234 stderr.printf ("Can't open database: %d, %s\n", rc, db.errmsg ()); 235 } 236 } 237 238 public void create_tables () { 239 int ec; 240 string? errmsg; 241 string create_font_table = """ 242 CREATE TABLE FallbackFont ( 243 unicode INTEGER PRIMARY KEY NOT NULL, 244 font_data TEXT NOT NULL 245 ); 246 """; 247 248 ec = db.exec (create_font_table, null, out errmsg); 249 if (ec != Sqlite.OK) { 250 warning ("Error: %s\n", (!) errmsg); 251 } 252 } 253 } 254 255 } 256