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 bf_parser = new BirdFontFile (new Font ()); 157 158 return bf_font; 159 } 160 161 public File get_database_file () { 162 return SearchPaths.find_file (null, "fallback-font.sqlite"); 163 } 164 165 public File get_new_database_file () { 166 string? fn = BirdFont.get_argument ("--fallback-font"); 167 168 if (fn != null && ((!) fn) != "") { 169 return File.new_for_path ((!) fn); 170 } 171 172 return File.new_for_path ("fallback-font.sqlite"); 173 } 174 175 public void generate_fallback_font () { 176 File f = get_new_database_file (); 177 string? fonts = BirdFont.get_argument ("--fonts"); 178 string fallback; 179 180 if (fonts == null) { 181 stderr.printf ("Add a list of fonts to use as fallback to the \"--fonts\" argument.\n"); 182 stderr.printf ("Separate each font file with \":\"\n"); 183 return; 184 } 185 186 fallback = (!) fonts; 187 188 stdout.printf ("Generating fallback font: %s\n", (!) f.get_path ()); 189 190 try { 191 if (f.query_exists ()) { 192 f.delete (); 193 } 194 195 open_database (f); 196 create_tables (); 197 198 foreach (string font in fallback.split (":")) { 199 add_font (font); 200 } 201 } catch (GLib.Error e) { 202 warning (e.message); 203 } 204 205 } 206 207 /* //FIXME:DELETE 208 public void add_font (string font_file) { 209 Font font; 210 Glyph g; 211 BirdFontFile bf; 212 File single_glyph_font; 213 214 font = new Font (); 215 single_glyph_font = File.new_for_path ("/tmp/fallback_glyph.bf"); 216 217 font.set_file (font_file); 218 if (!font.load ()) { 219 stderr.printf ("Failed to load font: " + font_file); 220 return; 221 } 222 223 for (int i = 0; i < font.length (); i++) { 224 g = (!) font.get_glyph_indice (i); 225 bf = new BirdFontFile (font); 226 } 227 } */ 228 229 public void open_database (File db_file) { 230 int rc = Database.open ((!) db_file.get_path (), out database); 231 232 db = (!) database; 233 234 if (rc != Sqlite.OK) { 235 stderr.printf ("Can't open database: %d, %s\n", rc, db.errmsg ()); 236 } 237 } 238 239 public void create_tables () { 240 int ec; 241 string? errmsg; 242 string create_font_table = """ 243 CREATE TABLE FallbackFont ( 244 unicode INTEGER PRIMARY KEY NOT NULL, 245 font_data TEXT NOT NULL 246 ); 247 """; 248 249 ec = db.exec (create_font_table, null, out errmsg); 250 if (ec != Sqlite.OK) { 251 warning ("Error: %s\n", (!) errmsg); 252 } 253 } 254 } 255 256 } 257