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