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