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

Revisions

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