The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

BirdFont.vala in libbirdfont

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
Add *nix as OS tag heads/master
1 /* 2 Copyright (C) 2012 2014 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 using BirdFont; 15 16 public const string GETTEXT_PACKAGE = "birdfont"; 17 18 namespace BirdFont { 19 20 public static string? settings_directory = null; 21 22 internal static string build_absoulute_path (string file_name) { 23 File f = File.new_for_path (file_name); 24 return (!) f.get_path (); 25 } 26 27 public static string get_version () { 28 return VERSION; 29 } 30 31 public static string get_os () { 32 #if MAC 33 return "mac"; 34 #else 35 if (BirdFont.win32) { 36 return "windows"; 37 } else { 38 return "free"; 39 } 40 #endif 41 } 42 43 public static void set_logging (bool log) { 44 BirdFont.logging = log; 45 } 46 47 public static string wine_to_unix_path (string exec_path) { 48 bool drive_c, drive_z; 49 int i; 50 string p, q; 51 52 p = exec_path; 53 p = p.replace ("\\", "/"); 54 55 drive_c = exec_path.index_of ("C:") == 0; 56 drive_z = exec_path.index_of ("Z:") == 0; 57 58 i = p.index_of (":"); 59 60 if (i != -1) { 61 p = p.substring (i + 2); 62 } 63 64 if (drive_c) { 65 q = @"/home/$(Environment.get_user_name ())/.wine/drive_c/" + p; 66 67 if (File.new_for_path (q).query_exists ()) { 68 return q; 69 } else { 70 return p; 71 } 72 } 73 74 if (drive_z) { 75 return ("/" + p).dup (); 76 } 77 78 return exec_path.dup (); 79 } 80 81 public bool is_null (void* n) { 82 return n == null; 83 } 84 85 public bool has_flag (uint32 flag, uint32 mask) { 86 return (flag & mask) > 0; 87 } 88 89 public class BirdFont { 90 public static Argument args; 91 public static bool experimental = false; 92 public static bool show_coordinates = false; 93 public static bool fatal_wanings = false; 94 public static bool win32 = false; 95 public static bool mac = false; 96 public static bool android = false; 97 public static string exec_path = ""; 98 public static string? bundle_path = null; 99 100 internal static bool logging = false; 101 public static DataOutputStream? logstream = null; 102 103 public static Font current_font; 104 public static GlyphCollection current_glyph_collection; 105 106 public static string? settings_subdirectory = null; 107 public static string? sandbox_directory = null; 108 109 public BirdFont () { 110 } 111 112 /** 113 * @param arg command line arguments 114 * @param program path 115 * @param setting subdirectory 116 */ 117 public void init (string[] arg, string? program_path, string? settings_subdir, string? sandbox_path) { 118 int i; 119 File font_file; 120 string exec_path; 121 string theme; 122 int default_theme_version; 123 string theme_version; 124 CharDatabaseParser parser; 125 CodePageBits codepage_bits; 126 127 set_settings_subdir (settings_subdir); 128 sandbox_directory = sandbox_path; 129 130 args = new Argument.command_line (arg); 131 Font.empty = new Font (); 132 133 #if ANDROID 134 BirdFont.logging = true; 135 136 __android_log_print (ANDROID_LOG_WARN, "BirdFont", @"libbirdfont version $VERSION"); 137 LogLevelFlags log_levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING; 138 Log.set_handler (null, log_levels, android_warning); 139 140 android = true; 141 #else 142 stdout.printf ("birdfont version %s\n", VERSION); 143 144 android = args.has_argument ("--android"); 145 146 if (!BirdFont.logging) { 147 BirdFont.logging = args.has_argument ("--log"); 148 } 149 #endif 150 151 if (BirdFont.logging) { 152 init_logfile (); 153 } 154 155 if (!args.has_argument ("--no-translation")) { 156 init_gettext (); 157 } 158 159 if (args.has_argument ("--help")) { 160 args.print_help (); 161 Process.exit (0); 162 } 163 164 #if !MAC 165 int err_arg = args.validate (); 166 if (err_arg != 0) { 167 stdout.printf (@"Unknown parameter $(arg [err_arg])\n\n"); 168 args.print_help (); 169 Process.exit (0); 170 } 171 #endif 172 Preferences.load (); 173 174 // always load default theme when names in theme does change 175 default_theme_version = 1; 176 theme = Preferences.get ("theme"); 177 theme_version = Preferences.get ("theme_version"); 178 179 Theme.set_default_colors (); 180 181 if (theme_version == "" || int.parse (theme_version) < default_theme_version) { 182 Theme.load_theme ("dark.theme"); 183 Preferences.set ("theme", "dark.theme"); 184 } else { 185 if (theme != "") { 186 Theme.load_theme (theme); 187 } else { 188 Theme.load_theme ("dark.theme"); 189 } 190 } 191 192 Preferences.set ("theme_version", @"$default_theme_version"); 193 194 current_font = new Font (); 195 current_font.set_name (""); 196 current_font.initialised = false; 197 current_glyph_collection = new GlyphCollection.with_glyph ('\0', ""); 198 199 experimental = args.has_argument ("--test"); 200 show_coordinates = args.has_argument ("--show-coordinates") || experimental; 201 fatal_wanings = args.has_argument ("--fatal-warning"); 202 win32 = (arg[0].index_of (".exe") > -1) 203 || arg[0] == "wine" 204 || args.has_argument ("--windows"); 205 206 #if MAC 207 mac = true; 208 #else 209 mac = args.has_argument ("--mac"); 210 #endif 211 212 if (program_path == null) { 213 exec_path = ""; 214 215 if (win32) { 216 // wine hack to get "." folder in win32 environment 217 i = arg[0].last_index_of ("\\"); 218 219 if (i != -1) { 220 exec_path = arg[0]; 221 exec_path = exec_path.substring (0, i); 222 exec_path = wine_to_unix_path (exec_path); 223 } 224 } else { 225 exec_path = "./"; 226 } 227 } else { 228 exec_path = (!) program_path; 229 } 230 231 if (args.get_file () != "") { 232 font_file = File.new_for_path (args.get_file ()); 233 234 if (!font_file.query_exists ()) { 235 stderr.printf (@"The file \"$(args.get_file ())\" was not found.\n"); 236 Process.exit (-1); 237 } 238 } 239 240 if (fatal_wanings) { 241 LogLevelFlags levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING; 242 Log.set_handler (null, levels, fatal_warning); 243 } 244 245 Preferences.set_last_file (get_current_font ().get_path ()); 246 247 DefaultCharacterSet.create_default_character_sets (); 248 DefaultCharacterSet.get_characters_for_prefered_language (); 249 250 HeadTable.init (1024); 251 252 if (TestBirdFont.get_singleton ().test_cases_to_run != "All") { 253 TestBirdFont.run_tests (); 254 } 255 256 if (has_argument ("--parse-ucd")) { 257 parser = new CharDatabaseParser (); 258 parser.regenerate_database (); 259 } 260 261 if (has_argument ("--codepages")) { 262 codepage_bits = new CodePageBits (); 263 codepage_bits.generate_codepage_database (); 264 } 265 266 ExportTool.generate_html_template (); 267 } 268 269 public static bool has_logging () { 270 bool log; 271 272 lock (BirdFont.logging) { 273 log = BirdFont.logging; 274 } 275 276 return log; 277 } 278 279 public static Argument get_arguments () { 280 return args; 281 } 282 283 public static void set_bundle_path (string path) { 284 bundle_path = path; 285 } 286 287 public static void init_gettext () { 288 // FIXME: android, this should be OK now 289 #if !ANDROID 290 string locale_directory = SearchPaths.get_locale_directory (); 291 Intl.setlocale (LocaleCategory.MESSAGES, ""); 292 Intl.bind_textdomain_codeset (GETTEXT_PACKAGE, "utf-8"); 293 Intl.bindtextdomain (GETTEXT_PACKAGE, locale_directory); 294 #endif 295 } 296 297 public static void load_font_from_command_line () { 298 string file = args.get_file (); 299 if (file != "") { 300 RecentFiles.load_font (file); 301 } 302 } 303 304 public static Font get_current_font () { 305 return current_font; 306 } 307 308 internal static void fatal_warning (string? log_domain, LogLevelFlags log_levels, string message) { 309 bool fatal = true; 310 311 if (log_domain != null) { 312 stderr.printf ("%s: \n", (!) log_domain); 313 } 314 315 stderr.printf ("\n%s\n\n", message); 316 assert (!fatal); 317 } 318 319 #if ANDROID 320 internal static void android_warning (string? log_domain, LogLevelFlags log_levels, string message) { 321 __android_log_print (ANDROID_LOG_WARN, "BirdFont", message); 322 } 323 #endif 324 325 public static Font new_font () { 326 current_font = new Font (); 327 328 if (!is_null (MainWindow.tools)) { 329 MainWindow.get_drawing_tools ().remove_all_grid_buttons (); 330 DrawingTools.add_new_grid (1, false); 331 DrawingTools.add_new_grid (2, false); 332 DrawingTools.add_new_grid (4, false); 333 } 334 335 if (!is_null (Toolbox.background_tools)) { 336 Toolbox.background_tools.remove_images (); 337 } 338 339 KerningTools.update_kerning_classes (); 340 341 return current_font; 342 } 343 344 public static string? get_sandbox_directory () { 345 return sandbox_directory; 346 } 347 348 public static void set_settings_directory (string directory) { 349 settings_subdirectory = directory; 350 } 351 352 public static File get_preview_directory () { 353 string? export = BirdFont.get_current_font ().get_export_directory (); 354 355 if (export == null) { 356 warning ("No export directory is set."); 357 export = ""; 358 } 359 360 File e = File.new_for_path ((!) export); 361 File p = get_child(e, "preview"); 362 363 return p; 364 } 365 366 public static void set_settings_subdir (string? subdir) { 367 settings_subdirectory = subdir; 368 } 369 370 internal static File get_settings_directory () { 371 string home_path; 372 File home; 373 File settings; 374 375 #if ANDROID 376 home_path = "/data/data/org.birdfont.sefyr/files"; 377 home = File.new_for_path (home_path); 378 379 if (!home.query_exists ()) { 380 printd ("Create settings directory."); 381 DirUtils.create ((!) home.get_path (),0755); 382 } 383 #else 384 if (sandbox_directory != null) { 385 home = File.new_for_path ((!) sandbox_directory); 386 } else { 387 home_path = (settings_directory != null) 388 ? (!) settings_directory : Environment.get_user_config_dir (); 389 390 if (is_null (home_path)) { 391 warning ("No home directory set."); 392 home_path = "."; 393 } 394 395 home = File.new_for_path (home_path); 396 } 397 #endif 398 399 if (settings_subdirectory != null) { 400 settings = get_child(home, (!) settings_subdirectory); 401 } else { 402 settings = get_child(home, "birdfont"); 403 } 404 405 if (!settings.query_exists ()) { 406 DirUtils.create ((!) settings.get_path (), 0755); 407 } 408 409 return settings; 410 } 411 412 public static bool has_argument (string param) { 413 if (is_null (args)) { 414 return false; 415 } 416 417 return args.has_argument (param); 418 } 419 420 internal static string? get_argument (string param) { 421 return args.get_argument (param); 422 } 423 424 public static void debug_message (string s) { 425 if (unlikely (has_logging ())) { 426 try { 427 if (BirdFont.logstream != null) { 428 ((!)BirdFont.logstream).put_string (s); 429 ((!)BirdFont.logstream).flush (); 430 } else { 431 warning ("No logstream."); 432 } 433 434 stderr.printf (s); 435 } catch (GLib.Error e) { 436 warning (e.message); 437 } 438 } 439 } 440 } 441 442 void init_logfile () { 443 DateTime t; 444 File settings; 445 string s; 446 File log; 447 448 try { 449 t = new DateTime.now_local (); 450 settings = BirdFont.get_settings_directory (); 451 s = t.to_string ().replace (":", "_"); 452 log = get_child (settings, @"birdfont_$s.log"); 453 454 BirdFont.logstream = new DataOutputStream (log.create (FileCreateFlags.REPLACE_DESTINATION)); 455 ((!)BirdFont.logstream).put_string ((!) log.get_path ()); 456 ((!)BirdFont.logstream).put_string ("\n"); 457 458 warning ("Logging to " + (!) log.get_path ()); 459 } catch (GLib.Error e) { 460 warning (e.message); 461 warning ((!) log.get_path ()); 462 } 463 464 LogLevelFlags levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING | LogLevelFlags.LEVEL_DEBUG; 465 Log.set_handler (null, levels, log_warning); 466 467 BirdFont.logging = true; 468 469 printd (@"Program version: $(VERSION)\n"); 470 } 471 472 internal static void log_warning (string? log_domain, LogLevelFlags log_levels, string message) { 473 if (log_domain != null) { 474 printd ((!) log_domain); 475 } 476 477 printd ("\n"); 478 printd (message); 479 printd ("\n"); 480 printd ("\n"); 481 } 482 483 /** Write debug output to logfile. */ 484 public static void printd (string s) { 485 #if ANDROID 486 __android_log_print (ANDROID_LOG_WARN, "BirdFont", s); 487 #else 488 BirdFont.debug_message (s); 489 #endif 490 } 491 492 /** Translate string */ 493 public string t_ (string t) { 494 #if ANDROID 495 return t; 496 #else 497 string translate = Preferences.get ("translate"); 498 499 if (translate == "" || translate == "true") { 500 return _(t); 501 } else { 502 return t; 503 } 504 #endif 505 } 506 507 /** Translate mac menu items */ 508 public static string translate_mac (string t) { 509 string s = t_(t); 510 return s.replace ("_", ""); 511 } 512 513 /** Print a warning if Birdfont was started with the --test argument. */ 514 public static void warn_if_test (string message) { 515 if (BirdFont.has_argument ("--test")) { 516 warning (message); 517 } 518 } 519 520 /** Obtain a handle to a file in a folder. */ 521 public static File get_child (File folder, string file_name) { 522 string f; 523 string s; 524 string n; 525 526 // avoid drive letter problems on windows 527 528 f = (!) folder.get_path (); 529 530 #if LINUX 531 s = "/"; 532 #else 533 s = (BirdFont.win32) ? "\\" : "/"; 534 #endif 535 536 n = file_name; 537 if (unlikely (BirdFont.win32 && file_name.index_of ("\\") != -1)) { 538 warning (@"File name contains path separator: $file_name, Directory: $f"); 539 n = n.substring (n.last_index_of ("\\")).replace ("\\", ""); 540 } 541 542 if (!f.has_suffix (s)) { 543 f += s; 544 } 545 546 printd (@"File in Directory: $f Name: $n\n"); 547 548 return File.new_for_path (f + n); 549 } 550 551 } 552