The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

ExportTool.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/ExportTool.vala.
Merge branch '2.14' of github.com:johanmattssonm/birdfont into 2.14
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 15 using B; 16 17 namespace BirdFont { 18 19 public class ExportTool : GLib.Object { 20 21 public ExportTool (string n) { 22 } 23 24 public static string export_selected_paths_to_svg () { 25 return export_current_glyph_to_string (true); 26 } 27 28 public static string export_selected_paths_to_inkscape_clipboard () { 29 return export_current_glyph_to_inkscape_clipboard (true); 30 } 31 32 public static string export_current_glyph_to_string (bool only_selected_paths = false) { 33 return export_to_string (MainWindow.get_current_glyph (), only_selected_paths); 34 } 35 36 public static string export_to_string (Glyph glyph, bool only_selected_paths) { 37 string name; 38 StringBuilder s; 39 40 name = XmlParser.encode (glyph.get_name ()); 41 s = new StringBuilder (); 42 43 s.append ("""<?xml version="1.0" encoding="utf-8"?> 44 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> 45 <svg version="1.0" 46 id="glyph_""" + name + """" 47 mlns="http://www.w3.org/2000/svg" 48 xmlns:xlink="http://www.w3.org/1999/xlink" 49 x="0px" 50 y="0px" 51 width=""" + "\"" + @"$(glyph.get_width ())" + """px" 52 height=""" + "\"" + @"$(glyph.get_height ())" + """px"> 53 """); 54 55 s.append (@"<g id=\"$(name)\">\n"); 56 57 s.append (get_svg_path_elements (glyph, only_selected_paths)); 58 59 s.append ("</g>\n"); 60 s.append ("</svg>"); 61 62 return s.str; 63 } 64 65 public static string export_current_glyph_to_inkscape_clipboard (bool only_selected_paths = false) { 66 return export_to_inkscape_clipboard (MainWindow.get_current_glyph (), only_selected_paths); 67 } 68 69 public static string export_to_inkscape_clipboard (Glyph glyph, bool only_selected_paths = false) { 70 StringBuilder s; 71 72 s = new StringBuilder (); 73 s.append ("""<?xml version="1.0" encoding="UTF-8" standalone="no"?>"""); 74 s.append ("\n"); 75 s.append ("<svg>\n"); 76 77 s.append ("""<inkscape:clipboard 78 id="clipboard3009" 79 style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" 80 min="0,0" 81 max="0,0" /> 82 """); 83 84 s.append (get_svg_path_elements (glyph, only_selected_paths)); 85 s.append ("</svg>"); 86 87 return s.str; 88 } 89 90 private static string get_svg_path_elements (Glyph glyph, bool only_selected_paths) { 91 string glyph_svg; 92 StringBuilder s; 93 string name; 94 int id = 0; 95 96 name = glyph.get_name (); 97 98 Gee.ArrayList<Path> pl; 99 100 s = new StringBuilder (); 101 glyph_svg = ""; 102 103 pl = only_selected_paths ? glyph.active_paths : glyph.get_visible_paths (); 104 foreach (Path p in pl) { 105 if (p.stroke > 0) { 106 s.append (@"<path "); 107 s.append (@"style=\""); 108 s.append (@"fill:none;"); 109 s.append (@"stroke:#000000;"); 110 s.append (@"stroke-width:$(p.stroke)px;"); 111 112 if (p.line_cap == LineCap.ROUND) { 113 s.append (@"stroke-linecap:round;"); 114 } else if (p.line_cap == LineCap.SQUARE) { 115 s.append (@"stroke-linecap:square;"); 116 } 117 118 s.append (@"\" "); 119 120 s.append (@"d=\"$(Svg.to_svg_path (p, glyph))\" id=\"path_$(name)_$(id)\" />\n"); 121 id++; 122 } 123 } 124 125 if (only_selected_paths) { 126 foreach (Path p in glyph.active_paths) { 127 if (p.stroke == 0) { 128 glyph_svg += Svg.to_svg_path (p, glyph); 129 } 130 } 131 } else { 132 foreach (Path p in glyph.get_visible_paths ()) { 133 if (p.stroke == 0) { 134 glyph_svg += Svg.to_svg_path (p, glyph); 135 } 136 } 137 } 138 139 if (glyph_svg != "") { 140 s.append (@"<path "); 141 s.append (@"style=\"fill:#000000;stroke-width:0px\" "); 142 s.append (@"d=\"$(glyph_svg)\" id=\"path_$(name)_$(id)\" />\n"); 143 id++; 144 } 145 146 return s.str; 147 } 148 149 public static void export_current_glyph () { 150 FileChooser fc = new FileChooser (); 151 fc.file_selected.connect ((selected_file) => { 152 Glyph glyph = MainWindow.get_current_glyph (); 153 FontDisplay fd = MainWindow.get_current_display (); 154 string glyph_svg; 155 string svg_file; 156 File file; 157 DataOutputStream os; 158 string name; 159 string fn; 160 int i; 161 162 if (fd is Glyph) { 163 glyph = MainWindow.get_current_glyph (); 164 } else if (fd is OverView) { 165 OverView overview = MainWindow.get_overview (); 166 Glyph? g = overview.get_selected_glyph (); 167 168 if (g == null) { 169 warning("No glyhp selected in overview."); 170 return; 171 } 172 173 glyph = (!) g; 174 } else { 175 return; 176 } 177 178 name = glyph.get_name (); 179 180 if (selected_file == null) { 181 return; 182 } 183 184 svg_file = (!) selected_file; 185 186 try { 187 #if MAC 188 file = File.new_for_path (svg_file); 189 #else 190 i = 1; 191 fn = svg_file.replace (".svg", ""); 192 file = File.new_for_path (fn + ".svg"); 193 while (file.query_exists ()) { 194 file = File.new_for_path (fn + @"$i.svg"); 195 i++; 196 } 197 #endif 198 glyph_svg = export_to_string (glyph, false); 199 os = new DataOutputStream (file.create(FileCreateFlags.REPLACE_DESTINATION)); 200 os.put_string (glyph_svg); 201 202 } catch (Error e) { 203 stderr.printf (@"Export \"$svg_file\" \n"); 204 critical (@"$(e.message)"); 205 } 206 }); 207 208 fc.add_extension ("svg"); 209 MainWindow.file_chooser (t_("Save"), fc, FileChooser.SAVE); 210 } 211 212 public static void generate_html_document (string html_file, Font font) { 213 File file = File.new_for_path (html_file); 214 DataOutputStream os; 215 string name; 216 217 #if MAC 218 name = ExportSettings.get_file_name_mac (font); 219 #else 220 name = ExportSettings.get_file_name (font); 221 #endif 222 try { 223 os = new DataOutputStream (file.create(FileCreateFlags.REPLACE_DESTINATION)); 224 225 os.put_string ( 226 """<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 227 <html> 228 <head> 229 230 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 231 <title>Lorem ipsum</title> 232 233 <style type="text/css"> 234 235 body { 236 text-rendering: optimizeLegibility; 237 font-feature-settings: "kern"; 238 -moz-font-feature-settings: "kern=1"; 239 -ms-font-feature-settings: "kern"; 240 -webkit-font-feature-settings: "kern"; 241 -o-font-feature-settings: "kern"; 242 } 243 244 @font-face { 245 font-family: '"""); os.put_string (@"$(name)"); os.put_string ("""SVG'; 246 src: url('"""); os.put_string (@"$(name).svg#$(name)"); os.put_string ("""') format('svg'); 247 } 248 """); 249 250 os.put_string (""" 251 @font-face { 252 font-family: '"""); os.put_string (@"$(name)"); os.put_string ("""TTF'; 253 src: url('"""); os.put_string (@"$(name).ttf"); os.put_string ("""') format('truetype'); 254 } 255 """); 256 257 os.put_string (""" 258 @font-face { 259 font-family: '"""); os.put_string (@"$(name)"); os.put_string ("""EOT'; 260 src: url('"""); os.put_string (@"$(name).eot"); os.put_string ("""'); 261 } 262 263 """); 264 265 os.put_string (""" 266 h1 { 267 font-weight:normal; 268 margin: 0 0 5px 0; 269 color: #afafaf; 270 } 271 272 h2 { 273 font-weight:normal; 274 margin: 0 0 5px 0; 275 color: #afafaf; 276 } 277 278 h3 { 279 font-weight:normal; 280 margin: 0 0 5px 0; 281 color: #afafaf; 282 } 283 284 h4 { 285 font-weight:normal; 286 margin: 0 0 5px 0; 287 color: #afafaf; 288 } 289 290 p { 291 margin: 0 0 5px 0; 292 color: #000000; 293 } 294 295 body { 296 margin: 30px 0 0 30px; 297 } 298 299 div { 300 font-family: """); 301 302 os.put_string ("'"); 303 os.put_string (@"$(name)"); 304 os.put_string ("EOT'"); 305 306 os.put_string (", '"); 307 os.put_string (@"$(name)"); 308 os.put_string ("TTF'"); 309 310 os.put_string (", '"); 311 os.put_string (@"$(name)"); 312 os.put_string ("SVG'"); 313 314 os.put_string (";"); 315 os.put_string (""" 316 margin: 0 0 30px 0; 317 } 318 319 h1.bigger { 320 font-size: 58pt; 321 } 322 323 h2.big { 324 font-size: 40pt; 325 } 326 327 h3.small { 328 font-size: 32pt; 329 } 330 331 h4.smaller { 332 font-size: 18pt; 333 } 334 335 h1.percent { 336 font-size: 100%; 337 } 338 339 p.bigger { 340 font-size: 32pt; 341 } 342 343 p.big { 344 font-size: 24pt; 345 } 346 347 p.small { 348 font-size: 18pt; 349 } 350 351 p.smaller { 352 font-size: 12pt; 353 } 354 355 span.swashes { 356 -moz-font-feature-settings: "swsh"; 357 -ms-font-feature-settings: "swsh"; 358 -webkit-font-feature-settings: "swsh"; 359 font-feature-settings: "swsh"; 360 } 361 362 span.alternates { 363 -moz-font-feature-settings: "salt" 1; 364 -ms-font-feature-settings: "salt" 1; 365 -webkit-font-feature-settings: "salt" 1; 366 font-feature-settings: "salt" 1; 367 } 368 369 span.smallcaps { 370 font-variant-caps: small-caps; 371 -moz-font-feature-settings: "smcp"; 372 -ms-font-feature-settings: "smcp"; 373 -webkit-font-feature-settings: "smcp"; 374 font-feature-settings: "smcp"; 375 } 376 377 span.capstosmallcaps { 378 font-variant-caps: all-small-caps; 379 -moz-font-feature-settings: "c2sc", "smcp"; 380 -ms-font-feature-settings: "c2sc", "smcp"; 381 -webkit-font-feature-settings: "c2sc", "smcp"; 382 font-feature-settings: "c2sc", "smcp"; 383 } 384 </style> 385 """); 386 387 os.put_string ( 388 """ 389 </head> 390 <body> 391 392 <div> 393 <h1 class="bigger">Lorem ipsum</h1> 394 <p class="bigger">Dolor sit amet!</p> 395 </div> 396 397 <div> 398 <h2 class="big">Hamburgerfonstiv</h2> 399 <p class="big">""" + name + """</p> 400 </div> 401 402 <div> 403 <h3 class="big"></h3> 404 <p class="big"> 405 <span class="capstosmallcaps">OTF</span> features, 406 <span class="swashes">like swashes </span> 407 <span class="alternates">alternates &amp; </span> 408 <span class="smallcaps">small caps</span>, can be added 409 to the font.</span> 410 </p> 411 </div> 412 413 <div> 414 <h4 class="smaller">Headline 16pt</h4> 415 <p class="smaller">Ett litet stycke svalhjärta.</p> 416 </div> 417 418 <div> 419 <h4 class="smaller">""" + t_("Alphabet") + """</h4> 420 <p class="smaller">""" + t_("a b c d e f g h i j k l m n o p q r s t u v w x y z") + """</p> 421 <p class="smaller">""" + t_("A B C D E F G H I J K L M N O P Q R S T U V W X Y Z") + """</p> 422 <p class="smaller">0 1 2 3 4 5 6 7 8 9</p> 423 </div> 424 425 </body> 426 </html> 427 """); 428 429 } catch (GLib.Error e) { 430 warning (e.message); 431 } 432 } 433 434 public static string get_export_folder () { 435 Font font = BirdFont.get_current_font (); 436 string? sandbox = BirdFont.get_sandbox_directory (); 437 438 if (sandbox != null) { 439 File s = File.new_for_path ((!) sandbox); 440 File f = get_child (s, "Fonts"); 441 try { 442 if (!f.query_exists ()) { 443 f.make_directory (); 444 } 445 } catch (GLib.Error e) { 446 warning(e.message); 447 } 448 return (!) get_child (f, font.full_name).get_path (); 449 } else { 450 return (!) font.get_folder ().get_path (); 451 } 452 } 453 454 public static File get_export_dir () { 455 return File.new_for_path (get_export_folder ()); 456 } 457 458 public static bool export_ttf_font () { 459 File f = get_export_dir (); 460 Font font = BirdFont.get_current_font (); 461 462 try { 463 if (!f.query_exists ()) { 464 f.make_directory (); 465 } 466 } catch (GLib.Error e) { 467 warning(e.message); 468 } 469 470 printd (@"export_ttf_font:\n"); 471 printd (@"get_export_folder (): $(get_export_folder ())\n"); 472 printd (@"font.get_path (): $(font.get_path ())\n"); 473 printd (@"font.get_folder_path (): $(font.get_folder_path ())\n"); 474 printd (@"font.get_folder (): $((!) f.get_path ())\n"); 475 476 return export_ttf_font_path (f); 477 } 478 479 public static bool export_ttf_font_path (File folder, bool use_export_settings = true) { 480 Font current_font = BirdFont.get_current_font (); 481 File ttf_file; 482 File ttf_file_mac; 483 File eot_file; 484 bool done = true; 485 string ttf_name; 486 string ttf_name_mac; 487 488 try { 489 ttf_name = ExportSettings.get_file_name (current_font) + ".ttf"; 490 ttf_name_mac = ExportSettings.get_file_name_mac (current_font) + ".ttf"; 491 492 if (ttf_name == ttf_name_mac) { 493 warning ("Same file name for the two ttf files."); 494 ttf_name_mac = ExportSettings.get_file_name_mac (current_font) + " Mac.ttf"; 495 } 496 497 ttf_file = get_child (folder, ttf_name); 498 ttf_file_mac = get_child (folder, ttf_name_mac); 499 eot_file = get_child (folder, ExportSettings.get_file_name (current_font) + ".eot"); 500 501 printd (@"Writing TTF fonts to $((!) ttf_file.get_path ())\n"); 502 503 if (ttf_file.query_exists ()) { 504 ttf_file.delete (); 505 } 506 507 if (ttf_file_mac.query_exists ()) { 508 ttf_file_mac.delete (); 509 } 510 511 if (eot_file.query_exists ()) { 512 eot_file.delete (); 513 } 514 515 write_ttf ((!) ttf_file.get_path (), (!) ttf_file_mac.get_path ()); 516 517 if (!use_export_settings || ExportSettings.export_eot_setting (current_font)) { 518 write_eot ((!) ttf_file.get_path (), (!) eot_file.get_path ()); 519 } 520 521 if (use_export_settings && !ExportSettings.export_ttf_setting (current_font)) { 522 if (ttf_file.query_exists ()) { 523 ttf_file.delete (); 524 } 525 } 526 } catch (Error e) { 527 critical (@"$(e.message)"); 528 done = false; 529 } 530 531 return done; 532 } 533 534 public static bool export_svg_font () { 535 return export_svg_font_path (get_export_dir ()); 536 } 537 538 public static bool export_svg_font_path (File folder) { 539 Font font = BirdFont.get_current_font (); 540 string file_name = @"$(ExportSettings.get_file_name (font)).svg"; 541 File file; 542 SvgFontFormatWriter fo; 543 544 try { 545 file = get_child (folder, file_name); 546 547 if (file.query_exists ()) { 548 file.delete (); 549 } 550 551 fo = new SvgFontFormatWriter (); 552 fo.open (file); 553 fo.write_font_file (font); 554 fo.close (); 555 } catch (Error e) { 556 critical (@"$(e.message)"); 557 return false; 558 } 559 560 return true; 561 } 562 563 static void write_ttf (string ttf, string ttf_mac) { 564 Font f = BirdFont.get_current_font (); 565 OpenFontFormatWriter fo = new OpenFontFormatWriter (f.units_per_em); 566 567 File file = (!) File.new_for_path (ttf); 568 File file_mac = (!) File.new_for_path (ttf_mac); 569 570 try { 571 fo.open (file, file_mac); 572 fo.write_ttf_font (f); 573 fo.close (); 574 } catch (Error e) { 575 warning (@"Can't write TTF font to $ttf"); 576 critical (@"$(e.message)"); 577 } 578 } 579 580 static void write_eot (string ttf, string eot) { 581 EotWriter fo = new EotWriter (ttf, eot); 582 583 try { 584 fo.write (); 585 } catch (Error e) { 586 warning (@"EOF conversion falied, $ttf -> $eot"); 587 critical (@"$(e.message)"); 588 } 589 } 590 } 591 592 } 593