.
1 /*
2 Copyright (C) 2012 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 using BirdFont;
15 public const string GETTEXT_PACKAGE = "birdfont";
16
17 namespace BirdFont {
18
19 public static string? settings_directory = null;
20
21 static void print_import_help (string[] arg) {
22 stdout.printf (t_("Usage:"));
23 stdout.printf (arg[0]);
24 stdout.printf (" " + t_("BF-FILE") + " " + t_("SVG-FILES ...") +"\n");
25 stdout.printf ("\n");
26 }
27
28 public static int run_import (string[] arg) {
29 string bf_file = "";
30 Gee.ArrayList<string> svg_files = new Gee.ArrayList<string> ();
31 File bf;
32 File svg;
33 Font font;
34 bool imported;
35
36 Preferences.load ();
37 BirdFont.args = new Argument ("");
38 BirdFont.current_font = new Font ();
39 BirdFont.current_glyph_collection = new GlyphCollection.with_glyph ('\0', "");
40 MainWindow.init ();
41
42 if (arg.length < 3) {
43 print_import_help (arg);
44 return -1;
45 }
46
47 bf_file = build_absoulute_path (arg[1]);
48
49 for (int i = 2; i < arg.length; i++) {
50 svg_files.add (arg[i]);
51 }
52
53 bf = File.new_for_path (bf_file);
54 foreach (string f in svg_files) {
55 svg = File.new_for_path (f);
56
57 if (!svg.query_exists ()) {
58 stdout.printf (@"$f " + t_("does not exist.") + "\n");
59 return -1;
60 }
61 }
62
63 font = BirdFont.get_current_font ();
64
65 if (!bf.query_exists ()) {
66 stdout.printf (@"$bf_file " + t_("does not exist.") + " ");
67 stdout.printf (t_("A new font will be created.") + "\n");
68 font.set_file (bf_file);
69 } else {
70 font.set_file (bf_file);
71 if (!font.load ()) {
72 warning (@"Failed to load font $bf_file.\n");
73
74 if (!bf_file.has_suffix (".bf")) {
75 warning (@"Is it a .bf file?\n");
76 }
77
78 return -1;
79 }
80 }
81
82 font.save_backup ();
83
84 foreach (string f in svg_files) {
85 svg = File.new_for_path (f);
86 imported = import_svg_file (font, svg);
87
88 if (!imported) {
89 stdout.printf (t_("Failed to import") + " " + f + "\n");
90 stdout.printf (t_("Aborting") + "\n");
91 return -1;
92 }
93 }
94
95 font.save_bf ();
96
97 return 0;
98 }
99
100 internal static string build_absoulute_path (string file_name) {
101 File f = File.new_for_path (file_name);
102 return (!) f.get_path ();
103 }
104
105 static bool import_svg_file (Font font, File svg_file) {
106 string file_name = (!) svg_file.get_basename ();
107 string glyph_name;
108 StringBuilder n;
109 Glyph glyph;
110 GlyphCollection? gc = null;
111 GlyphCollection glyph_collection;
112 unichar character;
113 GlyphCanvas canvas;
114
115 glyph_name = file_name.replace (".svg", "");
116 glyph_name = glyph_name.replace (".SVG", "");
117
118 if (glyph_name.char_count () > 1) {
119 if (glyph_name.has_prefix ("U+")) {
120 n = new StringBuilder ();
121 n.append_unichar (Font.to_unichar (glyph_name));
122 glyph_name = n.str;
123 gc = font.get_glyph_collection (glyph_name);
124 } else {
125 gc = font.get_glyph_collection_by_name (glyph_name);
126
127 if (gc == null) {
128 stdout.printf (file_name + " " + t_("is not the name of a glyph or a Unicode value.") + "\n");
129 stdout.printf (t_("Unicode values must start with U+.") + "\n");
130 return false;
131 }
132 }
133 } else {
134 gc = font.get_glyph_collection (glyph_name);
135 }
136
137 if (gc != null) {
138 glyph_collection = (!) gc;
139 character = glyph_collection.get_unicode_character ();
140 glyph = new Glyph (glyph_collection.get_name (), character);
141 glyph.version_id = glyph_collection.get_last_id () + 1;
142 glyph_collection.insert_glyph (glyph, true);
143 } else {
144 return_val_if_fail (glyph_name.char_count () == 1, false);
145 character = glyph_name.get_char (0);
146 glyph_collection = new GlyphCollection (character, glyph_name);
147 glyph = new Glyph (glyph_name, character);
148 glyph_collection.insert_glyph (glyph, true);
149 font.add_glyph_collection (glyph_collection);
150 }
151
152 canvas = MainWindow.get_glyph_canvas ();
153 canvas.set_current_glyph_collection (glyph_collection);
154
155 stdout.printf (t_("Adding"));
156 stdout.printf (" ");
157 stdout.printf ((!) svg_file.get_basename ());
158 stdout.printf (" ");
159 stdout.printf (t_("to"));
160 stdout.printf (" ");
161 stdout.printf (t_("Glyph"));
162 stdout.printf (": ");
163 stdout.printf (glyph.get_name ());
164 stdout.printf (" ");
165 stdout.printf (t_("Version"));
166 stdout.printf (": ");
167 stdout.printf (@"$(glyph.version_id)");
168 stdout.printf ("\n");
169
170 SvgParser.import_svg ((!) svg_file.get_path ());
171
172 return true;
173 }
174
175 static void print_export_help (string[] arg) {
176 stdout.printf (t_("Usage:"));
177 stdout.printf (arg[0]);
178 stdout.printf (" [" + t_("OPTION") + "...] " + t_("FILE") +"\n");
179 stdout.printf ("-h, --help " + t_("print this message\n"));
180 stdout.printf ("-o, --output [DIRECTORY] " + t_("write files to this directory\n"));
181 stdout.printf ("-s, --svg " + t_("write svg file\n"));
182 stdout.printf ("-t, --ttf " + t_("write ttf and eot files\n"));
183 stdout.printf ("\n");
184 }
185
186 public static string get_version () {
187 return VERSION;
188 }
189
190 public static string get_build_stamp () {
191 return BUILD_TIMESTAMP;
192 }
193
194 public static int run_export (string[] arg) {
195 string output_directory = ".";
196 string file_name = "";
197 bool specific_formats = false;
198 bool write_ttf = false;
199 bool write_svg = false;
200 File directory;
201 Font font;
202 MainWindow main_window;
203
204 stdout.printf ("birdfont-export version %s\n", VERSION);
205 stdout.printf ("built on %s\n", BUILD_TIMESTAMP);
206
207 if (arg.length < 2) {
208 print_export_help (arg);
209 return -1;
210 }
211
212 BirdFont.current_font = BirdFont.new_font ();
213 BirdFont.current_glyph_collection = new GlyphCollection.with_glyph ( '\0', "null");
214 main_window = new MainWindow ();
215
216 // FIXME: create a option for this and add structure the log messages
217 // init_logfile ();
218
219 for (int i = 1; i < arg.length; i++) {
220
221 if (arg[i] == "-f" || arg[i] == "--fatal-warnings") {
222 BirdFont.fatal_wanings = true;
223 return 0;
224 }
225
226 if (arg[i] == "-h" || arg[i] == "--help") {
227 print_export_help (arg);
228 return 0;
229 }
230
231 if ((arg[i] == "-o" || arg[i] == "--output") && i + 1 < arg.length) {
232 output_directory = arg[i + 1];
233 i++;
234 continue;
235 }
236
237 if (arg[i] == "-s" || arg[i] == "--svg") {
238 write_svg = true;
239 specific_formats = true;
240 continue;
241 }
242
243 if (arg[i] == "-t" || arg[i] == "--ttf") {
244 write_ttf = true;
245 specific_formats = true;
246 continue;
247 }
248
249 if (arg[i].has_prefix ("-")) {
250 print_export_help (arg);
251 return 1;
252 }
253
254 if (!arg[i].has_prefix ("-")) {
255 file_name = arg[i];
256
257 if (i != arg.length - 1) {
258 print_export_help (arg);
259 return 1;
260 }
261
262 break;
263 }
264 }
265
266 if (BirdFont.fatal_wanings) {
267 LogLevelFlags levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING;
268 Log.set_handler (null, levels, BirdFont.fatal_warning);
269 }
270
271 Preferences.load ();
272
273 BirdFont.args = new Argument ("");
274 BirdFont.current_glyph_collection = new GlyphCollection.with_glyph ('\0', "");
275
276 file_name = build_absoulute_path (file_name);
277
278 font = BirdFont.get_current_font ();
279 font.set_file (file_name);
280 if (!font.load ()) {
281 warning (@"Failed to load font $file_name.\n");
282
283 if (!file_name.has_suffix (".bf")) {
284 warning (@"Is it a .bf file?\n");
285 }
286
287 return 1;
288 }
289
290 directory = File.new_for_path (output_directory);
291
292 if (!directory.query_exists ()) {
293 stderr.printf (t_("Can't find output directory") + @"$((!)directory.get_path ())\n");
294 return 1;
295 }
296
297 if (!specific_formats || write_svg) {
298 print (@"Writing $(BirdFont.current_font.get_full_name ()).svg to $output_directory\n");
299 ExportTool.export_svg_font_path (File.new_for_path (output_directory));
300 }
301
302 if (!specific_formats || write_ttf) {
303 print (@"Writing $(BirdFont.current_font.get_full_name ()).ttf to $output_directory\n");
304 ExportTool.export_ttf_font_path (File.new_for_path (output_directory));
305 }
306
307 return 0;
308 }
309
310 public static string wine_to_unix_path (string exec_path) {
311 bool drive_c, drive_z;
312 int i;
313 string p, q;
314
315 p = exec_path;
316 p = p.replace ("\\", "/");
317
318 drive_c = exec_path.index_of ("C:") == 0;
319 drive_z = exec_path.index_of ("Z:") == 0;
320
321 i = p.index_of (":");
322
323 if (i != -1) {
324 p = p.substring (i + 2);
325 }
326
327 if (drive_c) {
328 q = @"/home/$(Environment.get_user_name ())/.wine/drive_c/" + p;
329
330 if (File.new_for_path (q).query_exists ()) {
331 return q;
332 } else {
333 return p;
334 }
335 }
336
337 if (drive_z) {
338 return ("/" + p).dup ();
339 }
340
341 return exec_path.dup ();
342 }
343
344 public bool is_null (void* n) {
345 return n == null;
346 }
347
348 public bool has_flag (uint32 flag, uint32 mask) {
349 return (flag & mask) > 0;
350 }
351
352 public class BirdFont {
353 public static Argument args;
354 public static bool experimental = false;
355 public static bool show_coordinates = false;
356 public static bool fatal_wanings = false;
357 public static bool win32 = false;
358 public static bool mac = false;
359 public static bool android = false;
360 public static string exec_path = "";
361 public static string bundle_path = "";
362
363 public static bool logging = false;
364 public static DataOutputStream? logstream = null;
365
366 public static Font current_font;
367 public static GlyphCollection current_glyph_collection;
368
369 public static Drawing? drawing = null;
370
371 public BirdFont () {
372 set_defaul_drawing_callbacks ();
373 }
374
375 void set_defaul_drawing_callbacks () {
376 if (drawing == null) {
377 drawing = new Drawing ();
378 }
379 }
380
381 /**
382 * @param arg command line arguments
383 * @param program path
384 */
385 public void init (string[] arg, string? program_path) {
386 int err_arg;
387 int i;
388 File font_file;
389 string exec_path;
390
391 args = new Argument.command_line (arg);
392
393 #if ANDROID
394 BirdFont.logging = true;
395
396 __android_log_print (ANDROID_LOG_WARN, "BirdFont", @"libbirdfont version $VERSION");
397 LogLevelFlags log_levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING;
398 Log.set_handler (null, log_levels, android_warning);
399
400 android = true;
401 #else
402 stdout.printf ("birdfont version %s\n", VERSION);
403 stdout.printf ("built on %s\n", BUILD_TIMESTAMP);
404
405 android = args.has_argument ("--android");
406 BirdFont.logging = args.has_argument ("--log");
407 #endif
408
409 if (BirdFont.logging) {
410 init_logfile ();
411 }
412
413 if (!args.has_argument ("--no-translation")) {
414 init_gettext ();
415 }
416
417 if (args.has_argument ("--help")) {
418 args.print_help ();
419 Process.exit (0);
420 }
421
422 err_arg = args.validate ();
423 if (err_arg != 0) {
424 stdout.printf (@"Unknown parameter $(arg [err_arg])\n\n");
425 args.print_help ();
426 Process.exit (0);
427 }
428
429 Preferences.load ();
430
431 // FIXME: DELETE
432 Theme.load_theme ();
433 save_default_colors ();
434
435 Theme.load_theme ();
436
437 current_font = new Font ();
438 current_font.set_name ("");
439 current_font.initialised = false;
440 current_glyph_collection = new GlyphCollection.with_glyph ('\0', "");
441
442 experimental = args.has_argument ("--test");
443 show_coordinates = args.has_argument ("--show-coordinates") || experimental;
444 fatal_wanings = args.has_argument ("--fatal-warning");
445 win32 = (arg[0].index_of (".exe") > -1)
446 || arg[0] == "wine"
447 || args.has_argument ("--windows");
448
449 #if MAC
450 mac = true;
451 #else
452 mac = args.has_argument ("--mac");
453 #endif
454
455 if (program_path == null) {
456 exec_path = "";
457
458 if (win32) {
459 // wine hack to get "." folder in win32 environment
460 i = arg[0].last_index_of ("\\");
461
462 if (i != -1) {
463 exec_path = arg[0];
464 exec_path = exec_path.substring (0, i);
465 exec_path = wine_to_unix_path (exec_path);
466 }
467 } else {
468 exec_path = "./";
469 }
470 } else {
471 exec_path = (!) program_path;
472 }
473
474 if (args.get_file () != "") {
475 font_file = File.new_for_path (args.get_file ());
476
477 if (!font_file.query_exists ()) {
478 stderr.printf (@"The file \"$(args.get_file ())\" was not found.\n");
479 Process.exit (-1);
480 }
481 }
482
483 if (fatal_wanings) {
484 LogLevelFlags levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING;
485 Log.set_handler (null, levels, fatal_warning);
486 }
487
488 Preferences.set_last_file (get_current_font ().get_path ());
489
490 DefaultCharacterSet.create_default_character_sets ();
491 DefaultCharacterSet.get_characters_for_prefered_language ();
492
493 HeadTable.init ();
494
495 if (TestBirdFont.get_singleton ().test_cases_to_run != "All") {
496 TestBirdFont.run_tests ();
497 }
498 }
499
500 public static Argument get_arguments () {
501 return args;
502 }
503
504 void save_default_colors () {
505 Theme.save_color ("Background 1", 1, 1, 1, 1);
506 Theme.save_color ("Background 2", 101 / 255.0, 108 / 255.0, 116 / 255.0, 1);
507 Theme.save_color ("Background 3", 38 / 255.0, 39 / 255.0, 43 / 255.0, 1);
508 Theme.save_color ("Background 4", 51 / 255.0, 54 / 255.0, 59 / 255.0, 1);
509 Theme.save_color ("Background 5", 0.3, 0.3, 0.3, 1);
510 Theme.save_color ("Background 6", 224/255.0, 224/255.0, 224/255.0, 1);
511 Theme.save_color ("Background 7", 56 / 255.0, 59 / 255.0, 65 / 255.0, 1);
512 Theme.save_color ("Background 8", 55/255.0, 55/255.0, 55/255.0, 1);
513 Theme.save_color ("Background 9", 72/255.0, 72/255.0, 72/255.0, 1);
514
515 Theme.save_color ("Foreground 1", 0, 0, 0, 1);
516 Theme.save_color ("Foreground 2", 101 / 255.0, 108 / 255.0, 116 / 255.0, 1);
517 Theme.save_color ("Foreground 3", 26 / 255.0, 30 / 255.0, 32 / 255.0, 1);
518 Theme.save_color ("Foreground 4", 40 / 255.0, 57 / 255.0, 65 / 255.0, 1);
519 Theme.save_color ("Foreground 5", 70 / 255.0, 77 / 255.0, 83 / 255.0, 1);
520
521 Theme.save_color ("Highlighted 1", 234 / 255.0, 77 / 255.0, 26 / 255.0, 1);
522
523 Theme.save_color ("Highlighted Guide", 0, 0, 0.3, 1);
524 Theme.save_color ("Guide 1", 0.7, 0.7, 0.8, 1);
525 Theme.save_color ("Guide 2", 0.7, 0, 0, 0.5);
526 Theme.save_color ("Guide 3", 120 / 255.0, 68 / 255.0, 120 / 255.0, 120 / 255.0);
527
528 Theme.save_color ("Grid",0.2, 0.6, 0.2, 0.2);
529
530 Theme.save_color ("Background Glyph", 0.2, 0.2, 0.2, 0.5);
531
532 Theme.save_color ("Tool Border 1", 38 / 255.0, 39 / 255.0, 43 / 255.0, 1);
533 Theme.save_color ("Tool Background 1", 14 / 255.0, 16 / 255.0, 17 / 255.0, 1);
534
535 Theme.save_color ("Tool Border 2", 38 / 255.0, 39 / 255.0, 43 / 255.0, 1);
536 Theme.save_color ("Tool Background 2", 26 / 255.0, 30 / 255.0, 32 / 255.0, 1);
537
538 Theme.save_color ("Tool Border 3", 38 / 255.0, 39 / 255.0, 43 / 255.0, 1);
539 Theme.save_color ("Tool Background 3", 44 / 255.0, 47 / 255.0, 51 / 255.0, 1);
540
541 Theme.save_color ("Tool Border 4", 38 / 255.0, 39 / 255.0, 43 / 255.0, 1);
542 Theme.save_color ("Tool Background 4", 33 / 255.0, 36 / 255.0, 39 / 255.0, 1);
543
544 Theme.save_color ("Button Foreground", 101 / 255.0, 108 / 255.0, 116 / 255.0, 1);
545
546 N_("Background 1");
547 N_("Background 2");
548 N_("Background 3");
549 N_("Background 4");
550 N_("Background 5");
551 N_("Background 6");
552 N_("Background 7");
553 N_("Background 8");
554 N_("Background 9");
555
556 N_("Foreground 1");
557 N_("Foreground 2");
558 N_("Foreground 3");
559 N_("Foreground 4");
560 N_("Foreground 5");
561
562 N_("Highlighted 1");
563 N_("Highlighted Guide");
564
565 N_("Grid");
566
567 N_("Guide 1");
568 N_("Guide 2");
569 N_("Guide 3");
570
571 N_("Tool Border 1");
572 N_("Tool Background 1");
573 N_("Tool Border 2");
574 N_("Tool Background 2");
575 N_("Tool Border 3");
576 N_("Tool Background 3");
577 N_("Tool Border 4");
578 N_("Tool Background 4");
579
580 N_("Button Foreground");
581 }
582
583 public static void set_bundle_path (string path) {
584 bundle_path = path;
585 }
586
587 public static void init_gettext () {
588 // FIXME: android, this should be OK now
589 #if !ANDROID
590 string locale_directory = SearchPaths.get_locale_directory ();
591 Intl.setlocale (LocaleCategory.MESSAGES, "");
592 Intl.bind_textdomain_codeset (GETTEXT_PACKAGE, "utf-8");
593 Intl.bindtextdomain (GETTEXT_PACKAGE, locale_directory);
594 #endif
595 }
596
597 public static void load_font_from_command_line () {
598 string file = args.get_file ();
599 if (file != "") {
600 FileTab.load_font (file);
601 }
602 }
603
604 public static Font get_current_font () {
605 return current_font;
606 }
607
608 internal static void fatal_warning (string? log_domain, LogLevelFlags log_levels, string message) {
609 bool fatal = true;
610
611 if (log_domain != null) {
612 stderr.printf ("%s: \n", (!) log_domain);
613 }
614
615 stderr.printf ("\n%s\n\n", message);
616 assert (!fatal);
617 }
618
619 #if ANDROID
620 internal static void android_warning (string? log_domain, LogLevelFlags log_levels, string message) {
621 __android_log_print (ANDROID_LOG_WARN, "BirdFont", message);
622 }
623 #endif
624
625 public static Font new_font () {
626 current_font = new Font ();
627
628 if (!is_null (MainWindow.tools)) {
629 MainWindow.get_drawing_tools ().remove_all_grid_buttons ();
630 MainWindow.get_drawing_tools ().add_new_grid (1);
631 MainWindow.get_drawing_tools ().add_new_grid (2);
632 MainWindow.get_drawing_tools ().add_new_grid (4);
633 }
634
635 if (!is_null (Toolbox.background_tools)) {
636 Toolbox.background_tools.remove_images ();
637 }
638
639 KerningTools.update_kerning_classes ();
640
641 return current_font;
642 }
643
644 public static void set_settings_directory (string directory) {
645 settings_directory = directory;
646 }
647
648 public static File get_preview_directory () {
649 File settings = get_settings_directory ();
650 File backup = get_child(settings, "preview");
651
652 if (!backup.query_exists ()) {
653 DirUtils.create ((!) backup.get_path (), 0755);
654 }
655
656 return backup;
657 }
658
659 internal static File get_thumbnail_directory () {
660 File thumbnails = get_child (get_settings_directory (), "thumbnails");
661
662 if (!thumbnails.query_exists ()) {
663 DirUtils.create ((!) thumbnails.get_path (), 0755);
664 }
665
666 return thumbnails;
667 }
668
669 internal static File get_settings_directory () {
670 string home_path;
671 File home;
672 File settings;
673
674 #if ANDROID
675 home_path = "/data/data/org.birdfont.sefyr/files";
676 home = File.new_for_path (home_path);
677
678 if (!home.query_exists ()) {
679 printd ("Create settings directory.");
680 DirUtils.create ((!) home.get_path (),0755);
681 }
682 #else
683 home_path = (settings_directory != null)
684 ? (!) settings_directory : Environment.get_user_config_dir ();
685
686 if (is_null (home_path)) {
687 warning ("No home directory set.");
688 home_path = ".";
689 }
690
691 home = File.new_for_path (home_path);
692 #endif
693 settings = get_child(home, "birdfont");
694
695 if (!settings.query_exists ()) {
696 DirUtils.create ((!) settings.get_path (), 0755);
697 }
698
699 return settings;
700 }
701
702 internal static File get_backup_directory () {
703 File settings = get_settings_directory ();
704 File backup = get_child (settings, "backup");
705
706 if (!backup.query_exists ()) {
707 DirUtils.create ((!) backup.get_path (), 0755);
708 }
709
710 return backup;
711 }
712
713 public static bool has_argument (string param) {
714 if (is_null (args)) {
715 return false;
716 }
717
718 return args.has_argument (param);
719 }
720
721 internal static string? get_argument (string param) {
722 return args.get_argument (param);
723 }
724 }
725
726 void init_logfile () {
727 DateTime t;
728 File settings;
729 string s;
730 File log;
731
732 try {
733 t = new DateTime.now_local ();
734 settings = BirdFont.get_settings_directory ();
735 s = t.to_string ().replace (":", "_");
736 log = get_child (settings, @"birdfont_$s.log");
737
738 BirdFont.logstream = new DataOutputStream (log.create (FileCreateFlags.REPLACE_DESTINATION));
739 ((!)BirdFont.logstream).put_string ((!) log.get_path ());
740 ((!)BirdFont.logstream).put_string ("\n");
741
742 warning ("Logging to " + (!) log.get_path ());
743 } catch (GLib.Error e) {
744 warning (e.message);
745 warning ((!) log.get_path ());
746 }
747
748 LogLevelFlags levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING | LogLevelFlags.LEVEL_DEBUG;
749 Log.set_handler (null, levels, log_warning);
750
751 BirdFont.logging = true;
752
753 printd (@"Program version: $(VERSION)\n");
754 printd (@"built on $(BUILD_TIMESTAMP)\n");
755 }
756
757 internal static void log_warning (string? log_domain, LogLevelFlags log_levels, string message) {
758 if (log_domain != null) {
759 printd ((!) log_domain);
760 }
761
762 printd ("\n");
763 printd (message);
764 printd ("\n");
765 printd ("\n");
766 }
767
768 /** Write debug output to logfile. */
769 void printd (string s) {
770 #if ANDROID
771 __android_log_print (ANDROID_LOG_WARN, "BirdFont", s);
772 #else
773 if (unlikely (BirdFont.logging)) {
774 try {
775 if (BirdFont.logstream != null) {
776 ((!)BirdFont.logstream).put_string (s);
777 } else {
778 warning ("No logstream.");
779 }
780
781 stderr.printf (s);
782 } catch (GLib.Error e) {
783 warning (e.message);
784 }
785 }
786 #endif
787 }
788
789 /** Translate string */
790 public string t_ (string t) {
791 return _(t);
792 }
793
794 /** Translate mac menu items */
795 public static string translate_mac (string t) {
796 string s = t_(t);
797 return s.replace ("_", "");
798 }
799
800 /** Print a warning if Birdfont was started with the --test argument. */
801 public static void warn_if_test (string message) {
802 if (BirdFont.has_argument ("--test")) {
803 warning (message);
804 }
805 }
806
807 /** Obtain a handle to a file in a folder. */
808 public static File get_child (File folder, string file_name) {
809 string f;
810 string s;
811 string n;
812
813 // avoid drive letter problems on windows
814
815 f = (!) folder.get_path ();
816 s = (BirdFont.win32) ? "\\" : "/";
817
818 n = file_name;
819 if (unlikely (BirdFont.win32 && file_name.index_of ("\\") != -1)) {
820 warning (@"File name contains path separator: $file_name, Directory: $f");
821 n = n.substring (n.last_index_of ("\\")).replace ("\\", "");
822 }
823
824 if (!f.has_suffix (s)) {
825 f += s;
826 }
827
828 printd (@"File: Directory: $f Name: $n\n");
829
830 return File.new_for_path (f + n);
831 }
832
833 public static void set_drawing_callbacks (Drawing callbacks) {
834 BirdFont.drawing = callbacks;
835 }
836
837 }
838