.
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