The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

ClipTool.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 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 namespace BirdFont { 16 17 public class ClipTool : Tool { 18 19 public static void copy_text (TextArea t) { 20 MainWindow.native_window.set_clipboard_text (t.get_selected_text ()); 21 } 22 23 public static void paste_text (TextArea t) { 24 if (t.carret_is_visible) { 25 t.insert_text (MainWindow.native_window.get_clipboard_text ()); 26 } 27 } 28 29 public static void copy () { 30 FontDisplay fd = MainWindow.get_current_display (); 31 string svg_data; 32 string bf_data; 33 string data; 34 35 if (fd is GlyphTab) { 36 svg_data = ExportTool.export_selected_paths_to_svg (); 37 38 bf_data = export_selected_paths_to_birdfont_clipboard (); 39 data = svg_data + bf_data; 40 MainWindow.native_window.set_clipboard (data); 41 MainWindow.native_window.set_inkscape_clipboard (data); 42 } else if (fd is OverView) { 43 copy_overview_glyphs (); 44 } else if (fd is DescriptionDisplay) { 45 DescriptionDisplay description_tab = (DescriptionDisplay) fd; 46 string t = description_tab.get_copy_selection (); 47 if (t != "") { 48 MainWindow.native_window.set_clipboard_text (t); 49 } 50 } else if (fd is ExportSettings) { 51 ExportSettings export_tab = (ExportSettings) fd; 52 string t = export_tab.get_copy_selection (); 53 if (t != "") { 54 MainWindow.native_window.set_clipboard_text (t); 55 } 56 } 57 } 58 59 /** Copy entire glyph. */ 60 public static void copy_glyph (Glyph glyph) { 61 string svg_data; 62 string bf_data; 63 string data; 64 65 svg_data = ExportTool.export_to_inkscape_clipboard (glyph, false); 66 bf_data = export_paths_to_birdfont_clipboard (false, false); 67 68 data = svg_data + bf_data; 69 MainWindow.native_window.set_clipboard (data); 70 MainWindow.native_window.set_inkscape_clipboard (data); 71 } 72 73 public static void copy_overview_glyphs () { 74 string svg_data = ""; 75 string bf_data = ""; 76 string data; 77 OverView o = MainWindow.get_overview (); 78 79 if (o.selected_items.size > 0) { 80 svg_data = ExportTool.export_to_inkscape_clipboard ( 81 o.selected_items.get (0).get_current (), false); 82 83 bf_data = export_paths_to_birdfont_clipboard (true, false); 84 85 data = svg_data + bf_data; 86 MainWindow.native_window.set_clipboard (data); 87 MainWindow.native_window.set_inkscape_clipboard (data); 88 } 89 } 90 91 public static void paste_in_place () { 92 paste_paths (true); 93 } 94 95 /** Paste at cursor. */ 96 public static void paste () { 97 FontDisplay fd = MainWindow.get_current_display (); 98 Glyph g = MainWindow.get_current_glyph (); 99 double x, y, w, h; 100 double dx, dy; 101 102 if (fd is GlyphTab) { 103 paste_paths (false); 104 105 g.selection_boundaries (out x, out y, out w, out h); 106 107 dx = g.motion_x - x - w / 2.0; 108 dy = g.motion_y - y + h / 2.0; 109 110 foreach (Path path in g.active_paths) { 111 path.move (dx, dy); 112 } 113 } else if (fd is SpacingTab) { 114 paste_letters_to_spacing_tab (); 115 } else if (fd is KerningDisplay) { 116 paste_letters_to_kerning_tab (); 117 } else if (fd is OverView) { 118 paste_to_overview (); 119 } else if (fd is DescriptionDisplay) { 120 DescriptionDisplay description_tab = (DescriptionDisplay) fd; 121 string clipboard_data = MainWindow.native_window.get_clipboard_data (); 122 123 if (!clipboard_data.has_prefix ("<?xml")) { 124 description_tab.paste (clipboard_data); 125 GlyphCanvas.redraw (); 126 } 127 } else if (fd is ExportSettings) { 128 ExportSettings export_tab = (ExportSettings) fd; 129 string clipboard_data = MainWindow.native_window.get_clipboard_data (); 130 131 if (!clipboard_data.has_prefix ("<?xml")) { 132 export_tab.paste (clipboard_data); 133 GlyphCanvas.redraw (); 134 } 135 } 136 } 137 138 static void paste_paths (bool paste_guide_lines) { 139 bool is_bf_clipboard; 140 FontDisplay fd; 141 string clipboard_data = MainWindow.native_window.get_clipboard_data (); 142 143 fd = MainWindow.get_current_display (); 144 145 // Determine if clipboard contains data in birdfont format. 146 is_bf_clipboard = clipboard_data.index_of ("BirdFontClipboard") > -1; 147 148 if (fd is GlyphTab) { 149 paste_to_glyph (is_bf_clipboard, paste_guide_lines); 150 } 151 152 BirdFont.get_current_font ().touch (); 153 } 154 155 static void paste_to_overview () { 156 string data = MainWindow.native_window.get_clipboard_data (); 157 import_birdfont_clipboard (data, true, true); 158 GlyphCanvas.redraw (); 159 } 160 161 static void paste_to_glyph (bool bf_clipboard_data, bool paste_guide_lines) { 162 FontDisplay fd = MainWindow.get_current_display (); 163 Glyph? destination = null; 164 string data; 165 return_if_fail (fd is GlyphTab); 166 167 GlyphTab glyph_tab = (GlyphTab) fd; 168 destination = glyph_tab.glyphs.get_current (); 169 ((!)destination).store_undo_state (); 170 ((!)destination).clear_active_paths (); 171 172 data = MainWindow.native_window.get_clipboard_data (); 173 174 if (bf_clipboard_data) { 175 import_birdfont_clipboard (data, paste_guide_lines, false); 176 } else if (data != "") { 177 SvgParser.import_svg_data (data, SvgFormat.INKSCAPE); 178 } 179 180 ((!)destination).update_view (); 181 } 182 183 static string export_selected_paths_to_birdfont_clipboard () { 184 return export_paths_to_birdfont_clipboard (false, true); 185 } 186 187 static string export_paths_to_birdfont_clipboard (bool overview, bool selected = false) { 188 StringBuilder s = new StringBuilder (); 189 Gee.ArrayList<Path> paths = new Gee.ArrayList<Path> (); 190 Path new_path; 191 Glyph glyph; 192 GlyphCollection glyph_collection; 193 OverView o; 194 195 if (overview) { 196 o = MainWindow.get_overview (); 197 unichar last_assigned = '\0'; 198 foreach (GlyphCollection gc in o.selected_items) { 199 s.append ("\n"); 200 s.append ("<!-- BirdFontClipboard\n"); 201 202 if (!gc.is_unassigned ()) { 203 last_assigned = gc.get_unicode_character (); 204 205 s.append ("BF glyph: "); 206 s.append (@"$(Font.to_hex (gc.get_unicode_character ()))"); 207 s.append ("\n"); 208 } else { 209 last_assigned++; 210 211 s.append ("BF glyph: "); 212 s.append (@"$(Font.to_hex (last_assigned))"); 213 s.append ("\n"); 214 } 215 216 s.append ("BF name: "); 217 s.append (@"$(gc.get_name ())"); 218 s.append ("\n"); 219 220 s.append ("BF unassigned: "); 221 s.append (@"$(gc.is_unassigned ())"); 222 s.append ("\n"); 223 224 s.append ("BF left: "); 225 s.append (@"$(gc.get_current ().left_limit)"); 226 s.append ("\n"); 227 228 s.append ("BF right: "); 229 s.append (@"$(gc.get_current ().right_limit)"); 230 s.append ("\n"); 231 232 foreach (Path path in gc.get_current ().get_visible_paths ()) { 233 s.append ("BF path: "); 234 s.append (BirdFontFile.get_point_data (path)); 235 s.append ("\n"); 236 237 s.append ("BF stroke: "); 238 s.append (@"$(path.stroke)"); 239 s.append ("\n"); 240 241 if (path.line_cap == LineCap.ROUND) { 242 s.append ("BF cap: round\n"); 243 } else if (path.line_cap == LineCap.SQUARE) { 244 s.append ("BF cap: square\n"); 245 } 246 } 247 248 s.append ("BF end -->"); 249 } 250 } else { 251 glyph = MainWindow.get_current_glyph (); 252 glyph_collection = MainWindow.get_current_glyph_collection (); 253 254 s.append ("\n"); 255 s.append ("<!-- BirdFontClipboard\n"); 256 257 s.append ("BF glyph: "); 258 s.append (@"$(Font.to_hex (glyph.unichar_code))"); 259 s.append ("\n"); 260 261 s.append ("BF name: "); 262 s.append (@"$(glyph_collection.get_name ())"); 263 s.append ("\n"); 264 265 s.append ("BF unassigned: "); 266 s.append (@"$(glyph_collection.is_unassigned ())"); 267 s.append ("\n"); 268 269 s.append ("BF left: "); 270 s.append (@"$(glyph.left_limit)"); 271 s.append ("\n"); 272 273 s.append ("BF right: "); 274 s.append (@"$(glyph.right_limit)"); 275 s.append ("\n"); 276 277 if (!selected) { 278 foreach (Path path in glyph.get_visible_paths ()) { 279 s.append ("BF path: "); 280 s.append (BirdFontFile.get_point_data (path)); 281 s.append ("\n"); 282 283 s.append ("BF stroke: "); 284 s.append (@"$(path.stroke)"); 285 s.append ("\n"); 286 287 if (path.line_cap == LineCap.ROUND) { 288 s.append ("BF cap: round\n"); 289 } else if (path.line_cap == LineCap.SQUARE) { 290 s.append ("BF cap: square\n"); 291 } 292 } 293 } else if (glyph.get_visible_paths ().size > 0) { 294 foreach (Path path in glyph.active_paths) { 295 s.append ("BF path: "); 296 s.append (BirdFontFile.get_point_data (path)); 297 s.append ("\n"); 298 299 s.append ("BF stroke: "); 300 s.append (@"$(path.stroke)"); 301 s.append ("\n"); 302 303 if (path.line_cap == LineCap.ROUND) { 304 s.append ("BF cap: round\n"); 305 } else if (path.line_cap == LineCap.SQUARE) { 306 s.append ("BF cap: square\n"); 307 } 308 } 309 } else { 310 new_path = new Path (); 311 foreach (Path path in glyph.get_visible_paths ()) { 312 if (path.points.size > 0 313 && path.points.get (0).is_selected () 314 && path.points.get (path.points.size - 1).is_selected ()) { 315 316 foreach (EditPoint ep in path.points) { 317 if (!ep.is_selected ()) { 318 path.set_new_start (ep); 319 break; 320 } 321 } 322 } 323 324 foreach (EditPoint ep in path.points) { 325 if (!ep.is_selected ()) { 326 if (path.points.size > 0) { 327 paths.add (new_path); 328 new_path = new Path (); 329 } 330 } else { 331 new_path.add_point (ep); 332 } 333 } 334 335 if (all_points_selected (path)) { 336 new_path.close (); 337 } 338 } 339 340 paths.add (new_path); 341 342 foreach (Path path in paths) { 343 if (path.points.size > 0) { 344 s.append ("BF path: "); 345 s.append (BirdFontFile.get_point_data (path)); 346 s.append ("\n"); 347 348 s.append ("BF stroke: "); 349 s.append (@"$(path.stroke)"); 350 s.append ("\n"); 351 352 if (path.line_cap == LineCap.ROUND) { 353 s.append ("BF cap: round\n"); 354 } else if (path.line_cap == LineCap.SQUARE) { 355 s.append ("BF cap: square\n"); 356 } 357 } 358 } 359 } 360 361 s.append ("BF end -->"); 362 } 363 364 return s.str; 365 } 366 367 static bool all_points_selected (Path p) { 368 foreach (EditPoint ep in p.points) { 369 if (!ep.is_selected ()) { 370 return false; 371 } 372 } 373 return true; 374 } 375 376 static void import_birdfont_clipboard (string data, bool paste_guide_lines, bool overview) { 377 Gee.ArrayList<GlyphCollection> glyphs = new Gee.ArrayList<GlyphCollection> (); 378 Glyph glyph = new Glyph ("null", '\0'); 379 string[] items = data.split ("\nBF "); 380 unichar c; 381 Glyph destination; 382 GlyphCollection glyph_collection = new GlyphCollection ('\0', ""); 383 OverView o; 384 Path path = new Path (); 385 386 foreach (string p in items) { 387 if (p.has_prefix ("glyph:")) { 388 p = p.replace ("glyph: ", ""); 389 p = p.replace ("\n", ""); 390 c = Font.to_unichar (p); 391 glyph_collection = new GlyphCollection (c, (!) c.to_string ()); 392 glyphs.add (glyph_collection); 393 394 glyph = new Glyph ((!) c.to_string (), c); 395 GlyphMaster master = new GlyphMaster (); 396 master.add_glyph (glyph); 397 glyph_collection.add_master (master); 398 } 399 400 if (p.has_prefix ("unassigned:")) { 401 p = p.replace ("unassigned: ", ""); 402 p = p.replace ("\n", ""); 403 glyph_collection.set_unassigned (bool.parse (p)); 404 } 405 406 if (p.has_prefix ("name:")) { 407 p = p.replace ("name: ", ""); 408 p = p.replace ("\n", ""); 409 glyph_collection.set_name (p); 410 glyph.name = p; 411 } 412 413 if (p.has_prefix ("path:")) { 414 p = p.replace ("path: ", ""); 415 p = p.replace ("\n", ""); 416 path = import_birdfont_path (glyph, p); 417 } 418 419 if (p.has_prefix ("left:")) { 420 glyph.left_limit = double.parse (p.replace ("left: ", "")); 421 glyph.remove_lines (); 422 glyph.add_help_lines (); 423 } 424 425 if (p.has_prefix ("right:")) { 426 glyph.right_limit = double.parse (p.replace ("right: ", "")); 427 glyph.remove_lines (); 428 glyph.add_help_lines (); 429 } 430 431 if (p.has_prefix ("stroke:")) { 432 path.stroke = double.parse (p.replace ("stroke: ", "")); 433 } 434 435 if (p.has_prefix ("cap:")) { 436 string cap = p.replace ("cap: ", ""); 437 438 if (cap == "round") { 439 path.line_cap = LineCap.ROUND; 440 } else if (cap == "square") { 441 path.line_cap = LineCap.SQUARE; 442 } 443 } 444 } 445 446 if (!overview) { 447 return_if_fail (glyphs.size > 0); 448 destination = MainWindow.get_current_glyph (); 449 glyph = glyphs.get (0).get_current (); 450 451 foreach (Path p in glyph.get_visible_paths ()) { 452 PenTool.clear_directions (); 453 destination.add_path (p); 454 destination.add_active_path (null, p); 455 } 456 457 if (paste_guide_lines) { 458 destination.left_limit = glyph.left_limit; 459 destination.right_limit = glyph.right_limit; 460 destination.add_help_lines (); 461 destination.update_other_spacing_classes (); 462 } 463 } else { 464 o = MainWindow.get_overview (); 465 o.copied_glyphs.clear (); 466 foreach (GlyphCollection gc in glyphs) { 467 o.copied_glyphs.add (gc); 468 } 469 o.paste (); 470 } 471 } 472 473 static Path import_birdfont_path (Glyph glyph, string data) { 474 Path path = new Path (); 475 476 BirdFontFile.parse_path_data (data, path); 477 478 if (path.points.size > 0) { 479 PenTool.clear_directions (); 480 glyph.add_path (path); 481 glyph.active_paths.add (path); 482 path.update_region_boundaries (); 483 } 484 485 PenTool.remove_all_selected_points (); 486 487 foreach (Path p in glyph.active_paths) { 488 if (p.is_open ()) { 489 foreach (EditPoint e in p.points) { 490 e.set_selected (true); 491 } 492 } 493 } 494 495 PenTool.update_selection (); 496 return path; 497 } 498 499 static void paste_letters_to_kerning_tab () { 500 string clipboard_data = MainWindow.native_window.get_clipboard_data (); 501 KerningDisplay kerning_display = MainWindow.get_kerning_display (); 502 503 if (!clipboard_data.has_prefix ("<?xml")) { 504 kerning_display.add_text (clipboard_data); 505 } 506 } 507 508 static void paste_letters_to_spacing_tab () { 509 string clipboard_data = MainWindow.native_window.get_clipboard_data (); 510 SpacingTab spacing_tab = MainWindow.get_spacing_tab (); 511 512 if (!clipboard_data.has_prefix ("<?xml")) { 513 spacing_tab.add_text (clipboard_data); 514 } 515 } 516 } 517 518 } 519