~ubuntu-branches/ubuntu/vivid/birdfont/vivid

« back to all changes in this revision

Viewing changes to libbirdfont/BirdFontPart.vala

  • Committer: Package Import Robot
  • Author(s): Hideki Yamane
  • Date: 2014-04-15 20:35:28 UTC
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: package-import@ubuntu.com-20140415203528-evwq2mnksme9fv0t
Tags: upstream-0.37
ImportĀ upstreamĀ versionĀ 0.37

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright (C) 2014 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
namespace BirdFont {
 
16
 
 
17
/** BirdFontPart is a class for parsing .bfp files. The file format is 
 
18
 * identical to .bf but the font is split in many parts. Each part
 
19
 * contains a few elements and all parent nodes from the root node and
 
20
 * downwards. The .bfp files can be parsed in any order. The root directory
 
21
 * of a .bfp tree must have a file with the name "description.bfp", this file 
 
22
 * tells the parser that bfp files in parent directories should be excluded.
 
23
 */
 
24
class BirdFontPart : GLib.Object{
 
25
        Font font;
 
26
        List<string> parts;
 
27
        string root_directory;
 
28
 
 
29
        static string FILE_ATTRIBUTES = "standard::*";
 
30
 
 
31
        public BirdFontPart (Font font) {       
 
32
                this.font = font;
 
33
                parts = new List<string> ();
 
34
                root_directory = "";
 
35
        }
 
36
 
 
37
        public bool load (string bfp_file) {
 
38
                BirdFontFile bf = new BirdFontFile (font);
 
39
                File bfp_dir;
 
40
                File image_dir;
 
41
                
 
42
                try {
 
43
                        find_all_parts (bfp_file);
 
44
                        font.set_bfp (true);
 
45
                        
 
46
                        while (font.background_images.length () > 0) {
 
47
                                font.background_images.remove_link (font.background_images.first ());
 
48
                        }
 
49
                        
 
50
                        bfp_dir = File.new_for_path (root_directory);
 
51
                        image_dir = bfp_dir.get_child ("images");
 
52
                        copy_backgrounds ((!) image_dir.get_path ());
 
53
 
 
54
                        foreach (string fn in parts) {
 
55
                                bf.load_part (fn);
 
56
                        }
 
57
                } catch (GLib.Error e) {
 
58
                        warning (e.message);
 
59
                        return false;
 
60
                }
 
61
                
 
62
                return true;
 
63
        }
 
64
        
 
65
        public string get_path () {
 
66
                string path = "";
 
67
                
 
68
                try {
 
69
                        path = (!) get_destination_file (@"$(font.full_name).bfp").get_path ();
 
70
                } catch (GLib.Error e) {
 
71
                        warning (e.message);
 
72
                }
 
73
                
 
74
                return path;
 
75
        }
 
76
        
 
77
        public bool save () {
 
78
                DataOutputStream os;
 
79
                BirdFontFile bf = new BirdFontFile (font);
 
80
                bool error = false;
 
81
                
 
82
                if (root_directory == "") {
 
83
                        warning ("No directory is created for this birdfont part.");
 
84
                        return false;
 
85
                }
 
86
                
 
87
                try {
 
88
                        os = create_file (@"$(font.full_name).bfp");
 
89
                        bf.write_root_tag (os);
 
90
                        bf.write_closing_root_tag (os);
 
91
                        os.close ();
 
92
                        
 
93
                        os = create_file ("description.bfp");
 
94
                        bf.write_root_tag (os);
 
95
                        bf.write_description (os);
 
96
                        bf.write_closing_root_tag (os);
 
97
                        os.close ();
 
98
 
 
99
                        os = create_file ("lines.bfp");
 
100
                        bf.write_root_tag (os);
 
101
                        bf.write_lines (os);
 
102
                        bf.write_closing_root_tag (os);
 
103
                        os.close ();
 
104
 
 
105
                        os = create_file ("settings.bfp");
 
106
                        bf.write_root_tag (os);
 
107
                        bf.write_settings (os);
 
108
                        bf.write_closing_root_tag (os);
 
109
                        os.close ();
 
110
 
 
111
                        font.glyph_cache.for_each ((gc) => {
 
112
                                try {
 
113
                                        string file_name;
 
114
                                        string dir_name;
 
115
                        
 
116
                                        if (is_null (gc)) {
 
117
                                                warning ("No glyph collection");
 
118
                                        }
 
119
 
 
120
                                        file_name = get_first_number_in_unicode (((!)gc).get_current ());
 
121
                                        dir_name = (!)file_name.get_char ().to_string ();
 
122
                                                                
 
123
                                        os = create_file (@"selected_$(file_name).bfp", "glyphs", dir_name);
 
124
                                        bf.write_root_tag (os);
 
125
                                        bf.write_glyph_collection_start (gc, os);
 
126
                                        bf.write_selected ((!) gc, os);
 
127
                                        bf.write_glyph_collection_end (os);
 
128
                                        bf.write_closing_root_tag (os);
 
129
                                        os.close ();
 
130
                        
 
131
                                        foreach (Glyph g in gc.get_version_list ().glyphs) {
 
132
                                                try {
 
133
                                                        write_glyph (bf, gc, g);
 
134
                                                        write_glyph_background_image (bf, gc, g);
 
135
                                                } catch (GLib.Error e) {
 
136
                                                        warning (e.message);
 
137
                                                }
 
138
                                        }
 
139
                                } catch (GLib.Error e) {
 
140
                                        warning (@"Can not save bfp files to $root_directory\n");
 
141
                                        warning (@"$(e.message) \n");
 
142
                                        error = true;
 
143
                                }
 
144
                        });
 
145
 
 
146
                        os = create_file ("kerning.bfp");
 
147
                        bf.write_root_tag (os);
 
148
                        bf.write_kerning (os);
 
149
                        bf.write_closing_root_tag (os);
 
150
                        os.close ();
 
151
                        
 
152
                } catch (GLib.Error e) {
 
153
                        warning (@"Failed to save bfp files to $root_directory\n");
 
154
                        warning (@"$(e.message) \n");
 
155
                        return false;
 
156
                }
 
157
                
 
158
                return error;
 
159
        }
 
160
 
 
161
        void copy_backgrounds (string folder) throws GLib.Error {
 
162
                FileInfo info;
 
163
                FileInfo? fi;
 
164
                FileEnumerator e;
 
165
                string name;
 
166
                File image_dir;
 
167
                GlyphBackgroundImage bg;
 
168
                File found;
 
169
                File dest;
 
170
                
 
171
                image_dir = File.new_for_path (folder);
 
172
                
 
173
                if (image_dir.query_exists ()) {
 
174
                        info = image_dir.query_info (FILE_ATTRIBUTES, FileQueryInfoFlags.NONE);
 
175
                        if (info.get_file_type () != FileType.DIRECTORY) {
 
176
                                warning (@"$((!) image_dir.get_path ()) is not a directory.");
 
177
                                throw new FileError.NOTDIR ("Not a directory.");
 
178
                        }
 
179
 
 
180
                        e = image_dir.enumerate_children (FILE_ATTRIBUTES, 0);
 
181
                        while ((fi = e.next_file ()) != null) {
 
182
                                info = (!) fi;
 
183
                                name = info.get_name ();
 
184
                                
 
185
                                if (info.get_file_type () == FileType.DIRECTORY) {
 
186
                                        found = image_dir.get_child (name);
 
187
                                        copy_backgrounds ((!) found.get_path ());
 
188
                                }
 
189
                                
 
190
                                if (name.has_suffix (".png")) {
 
191
                                        found = image_dir.get_child (name);
 
192
                                        dest = font.get_backgrounds_folder ().get_child ("parts").get_child (name);
 
193
                                        bg = new GlyphBackgroundImage ((!) found.get_path ());
 
194
                                        bg.create_background_folders (font);
 
195
                                        bg.copy_if_new (dest);
 
196
                                }
 
197
                        }
 
198
                }
 
199
        }
 
200
 
 
201
        string get_first_number_in_unicode (Glyph g) throws GLib.Error {
 
202
                string s = Font.to_hex (g.unichar_code);
 
203
                s = s.replace ("U+", "");
 
204
                return s;
 
205
        }
 
206
        
 
207
        string get_glyph_base_file_name (Glyph g) throws GLib.Error {
 
208
                string s = get_first_number_in_unicode (g);
 
209
                s = @"$(s)_$(g.version_id)";
 
210
                return s;
 
211
        }
 
212
 
 
213
        void write_glyph (BirdFontFile bf, GlyphCollection gc, Glyph g) throws GLib.Error {
 
214
                string file_name;
 
215
                string dir_name;
 
216
                DataOutputStream os;
 
217
         
 
218
                file_name = get_glyph_base_file_name (g);
 
219
                dir_name = (!)file_name.get_char ().to_string ();
 
220
                                        
 
221
                os = create_file (@"$(file_name).bfp", "glyphs", dir_name);
 
222
                bf.write_root_tag (os);
 
223
                bf.write_glyph_collection_start (gc, os);
 
224
                bf.write_glyph (g, gc, os);
 
225
                bf.write_glyph_collection_end (os);
 
226
                bf.write_closing_root_tag (os);
 
227
                os.close ();
 
228
        }
 
229
 
 
230
        void write_glyph_background_image (BirdFontFile bf, GlyphCollection gc, Glyph g) throws GLib.Error {
 
231
                string file_name;
 
232
                string dir_name;
 
233
                GlyphBackgroundImage bg;
 
234
                File file;
 
235
                
 
236
                if (g.get_background_image () != null) {
 
237
                        bg = (!) g.get_background_image ();
 
238
 
 
239
                        if (bg.is_valid ()) {
 
240
                                file_name = @"$(bg.get_sha1 ()).png";
 
241
                                dir_name = (!)file_name.get_char ().to_string ();
 
242
                                file = get_destination_file (file_name, "images", dir_name);
 
243
                                bg.copy_if_new (file);                          
 
244
                                
 
245
                                // FIXME: GIT ADD
 
246
                        }                       
 
247
                }
 
248
        }
 
249
                
 
250
        public void create_directory (string directory) throws GLib.Error {     
 
251
                File dir = File.new_for_path (directory);
 
252
                File bfp_dir;
 
253
                int i = 2;
 
254
                
 
255
                if (directory.has_suffix (font.get_full_name ())) {
 
256
                        bfp_dir = dir;
 
257
                } else {
 
258
                        bfp_dir = dir.get_child (font.get_full_name ());
 
259
                }
 
260
                
 
261
                while (bfp_dir.query_exists ()) {
 
262
                        bfp_dir = dir.get_child (@"$(font.get_full_name ())_$(i)");
 
263
                        i++;
 
264
                }
 
265
                
 
266
                if (!dir.query_exists ()) {
 
267
                        DirUtils.create ((!) dir.get_path (), 0xFFFFFF);
 
268
                }
 
269
                
 
270
                root_directory = (!) bfp_dir.get_path ();
 
271
                DirUtils.create (root_directory, 0xFFFFFF);
 
272
        }
 
273
 
 
274
        private void find_all_parts (string bfp_file) throws GLib.Error {       
 
275
                File start = File.new_for_path (bfp_file);
 
276
                FileInfo info;
 
277
                File root;
 
278
                
 
279
                info = start.query_info (FILE_ATTRIBUTES, FileQueryInfoFlags.NONE);
 
280
                if (info.get_file_type () != FileType.DIRECTORY) {
 
281
                        start = (!) start.get_parent ();
 
282
                }
 
283
 
 
284
                root = find_root ((!)start.get_path ());
 
285
                root_directory = (!)root.get_path ();
 
286
 
 
287
                find_parts (root_directory);
 
288
        }
 
289
 
 
290
        private void find_parts (string directory) throws GLib.Error {  
 
291
                File start = File.new_for_path (directory);
 
292
                File found;
 
293
                FileInfo info;
 
294
                FileInfo? fi;
 
295
                FileEnumerator e;
 
296
                string name;
 
297
                
 
298
                
 
299
                info = start.query_info (FILE_ATTRIBUTES, FileQueryInfoFlags.NONE);
 
300
                if (info.get_file_type () != FileType.DIRECTORY) {
 
301
                        warning (@"$directory is not a directory.");
 
302
                        throw new FileError.NOTDIR ("Not a directory.");
 
303
                }
 
304
 
 
305
                e = start.enumerate_children (FILE_ATTRIBUTES, 0);
 
306
                while ((fi = e.next_file ()) != null) {
 
307
                        info = (!) fi;
 
308
                        name = info.get_name ();
 
309
                        if (info.get_file_type () == FileType.DIRECTORY) {
 
310
                                find_parts ((!) ((!) start.get_child (name)).get_path ());
 
311
                        } else if (name.has_suffix (".bfp")) {
 
312
                                found = start.get_child (name);
 
313
                                parts.append ((!) found.get_path ());
 
314
                        }
 
315
                }
 
316
        }
 
317
                
 
318
        private File find_root (string directory) throws GLib.Error {
 
319
                File start = File.new_for_path (directory);
 
320
                FileInfo info;
 
321
                FileInfo? fi;
 
322
                FileEnumerator e;
 
323
                
 
324
                info = start.query_info (FILE_ATTRIBUTES, FileQueryInfoFlags.NONE);
 
325
                if (info.get_file_type () != FileType.DIRECTORY) {
 
326
                        warning ("Not a directory.");
 
327
                        throw new FileError.NOTDIR ("Not a directory.");
 
328
                }
 
329
 
 
330
                e = start.enumerate_children (FILE_ATTRIBUTES, 0);
 
331
                while ((fi = e.next_file ()) != null) {
 
332
                        info = (!) fi;
 
333
                        if (info.get_name () == "description.bfp") {
 
334
                                return start;
 
335
                        }
 
336
                }
 
337
                
 
338
                if (start.get_parent () == null) {
 
339
                        warning ("description.bfp not found");
 
340
                        throw new FileError.FAILED ("description.bfp not found");
 
341
                }
 
342
                
 
343
                return find_root ((!)((!) start.get_parent ()).get_path ());
 
344
        }
 
345
        
 
346
        private File new_subdirectory (File d, string subdir) throws GLib.Error {
 
347
                FileInfo info;
 
348
                File dir;
 
349
                
 
350
                dir = d;
 
351
                dir = dir.get_child (subdir);
 
352
                
 
353
                if (!dir.query_exists ()) {
 
354
                        DirUtils.create ((!) dir.get_path (), 0xFFFFFF);
 
355
                } else {
 
356
                        info = dir.query_info (FILE_ATTRIBUTES, FileQueryInfoFlags.NONE);
 
357
                        if (info.get_file_type () != FileType.DIRECTORY) {
 
358
                                throw new FileError.FAILED (@"Can't save font, $subdir is not a directory.");
 
359
                        }
 
360
                }
 
361
                return dir;
 
362
        }
 
363
        
 
364
        private File get_destination_file (string name, string subdir1 = "", string subdir2 = "") throws GLib.Error {
 
365
                File file;
 
366
                File dir;
 
367
 
 
368
                dir = File.new_for_path (root_directory);
 
369
                
 
370
                if (subdir1 != "") {
 
371
                        dir = new_subdirectory (dir, subdir1);
 
372
                }
 
373
 
 
374
                if (subdir2 != "") {
 
375
                        dir = new_subdirectory (dir, subdir2);
 
376
                }
 
377
                                
 
378
                file = dir.get_child (name);
 
379
 
 
380
                if (file.query_file_type (0) == FileType.DIRECTORY) {
 
381
                        throw new FileError.FAILED (@"Can't save font, $name is a directory.");
 
382
                }
 
383
                
 
384
                return file;
 
385
        }
 
386
        
 
387
        private DataOutputStream create_file (string name, string subdir1 = "", string subdir2 = "") throws GLib.Error {
 
388
                DataOutputStream os;
 
389
                File file;
 
390
                
 
391
                file = get_destination_file (name, subdir1, subdir2);
 
392
                
 
393
                if (file.query_exists ()) {
 
394
                        file.delete ();
 
395
                }
 
396
                
 
397
                os = new DataOutputStream (file.create (FileCreateFlags.REPLACE_DESTINATION));
 
398
                
 
399
                // FIXME: GIT ADD
 
400
                
 
401
                return os;
 
402
        }
 
403
}
 
404
 
 
405
}