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

Revisions

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