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.
Redraw after switching from rsb to lsb in spacing tab
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 } 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 GlyphTab) { 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 GlyphTab) { 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 GlyphTab); 136 137 GlyphTab glyph_tab = (GlyphTab) fd; 138 destination = glyph_tab.glyphs.get_current (); 139 ((!)destination).store_undo_state (); 140 ((!)destination).clear_active_paths (); 141 142 data = MainWindow.native_window.get_clipboard_data (); 143 144 if (bf_clipboard_data) { 145 import_birdfont_clipboard (data, paste_guide_lines, false); 146 } else if (data != "") { 147 SvgParser.import_svg_data (data, SvgFormat.INKSCAPE); 148 } 149 150 ((!)destination).update_view (); 151 } 152 153 static string export_selected_paths_to_birdfont_clipboard () { 154 return export_paths_to_birdfont_clipboard (false, true); 155 } 156 157 static string export_paths_to_birdfont_clipboard (bool overview, bool selected = false) { 158 StringBuilder s = new StringBuilder (); 159 Gee.ArrayList<Path> paths = new Gee.ArrayList<Path> (); 160 Path new_path; 161 Glyph glyph; 162 GlyphCollection glyph_collection; 163 OverView o; 164 165 if (overview) { 166 o = MainWindow.get_overview (); 167 unichar last_assigned = '\0'; 168 foreach (GlyphCollection gc in o.selected_items) { 169 s.append ("\n"); 170 s.append ("<!-- BirdFontClipboard\n"); 171 172 if (!gc.is_unassigned ()) { 173 last_assigned = gc.get_unicode_character (); 174 175 s.append ("BF glyph: "); 176 s.append (@"$(Font.to_hex (gc.get_unicode_character ()))"); 177 s.append ("\n"); 178 } else { 179 last_assigned++; 180 181 s.append ("BF glyph: "); 182 s.append (@"$(Font.to_hex (last_assigned))"); 183 s.append ("\n"); 184 } 185 186 s.append ("BF name: "); 187 s.append (@"$(gc.get_name ())"); 188 s.append ("\n"); 189 190 s.append ("BF unassigned: "); 191 s.append (@"$(gc.is_unassigned ())"); 192 s.append ("\n"); 193 194 s.append ("BF left: "); 195 s.append (@"$(gc.get_current ().left_limit)"); 196 s.append ("\n"); 197 198 s.append ("BF right: "); 199 s.append (@"$(gc.get_current ().right_limit)"); 200 s.append ("\n"); 201 202 foreach (Path path in gc.get_current ().get_visible_paths ()) { 203 s.append ("BF path: "); 204 s.append (BirdFontFile.get_point_data (path)); 205 s.append ("\n"); 206 207 s.append ("BF stroke: "); 208 s.append (@"$(path.stroke)"); 209 s.append ("\n"); 210 211 if (path.line_cap == LineCap.ROUND) { 212 s.append ("BF cap: round\n"); 213 } else if (path.line_cap == LineCap.SQUARE) { 214 s.append ("BF cap: square\n"); 215 } 216 } 217 218 s.append ("BF end -->"); 219 } 220 } else { 221 glyph = MainWindow.get_current_glyph (); 222 glyph_collection = MainWindow.get_current_glyph_collection (); 223 224 s.append ("\n"); 225 s.append ("<!-- BirdFontClipboard\n"); 226 227 s.append ("BF glyph: "); 228 s.append (@"$(Font.to_hex (glyph.unichar_code))"); 229 s.append ("\n"); 230 231 s.append ("BF name: "); 232 s.append (@"$(glyph_collection.get_name ())"); 233 s.append ("\n"); 234 235 s.append ("BF unassigned: "); 236 s.append (@"$(glyph_collection.is_unassigned ())"); 237 s.append ("\n"); 238 239 s.append ("BF left: "); 240 s.append (@"$(glyph.left_limit)"); 241 s.append ("\n"); 242 243 s.append ("BF right: "); 244 s.append (@"$(glyph.right_limit)"); 245 s.append ("\n"); 246 247 if (!selected) { 248 foreach (Path path in glyph.get_visible_paths ()) { 249 s.append ("BF path: "); 250 s.append (BirdFontFile.get_point_data (path)); 251 s.append ("\n"); 252 253 s.append ("BF stroke: "); 254 s.append (@"$(path.stroke)"); 255 s.append ("\n"); 256 257 if (path.line_cap == LineCap.ROUND) { 258 s.append ("BF cap: round\n"); 259 } else if (path.line_cap == LineCap.SQUARE) { 260 s.append ("BF cap: square\n"); 261 } 262 } 263 } else if (glyph.get_visible_paths ().size > 0) { 264 foreach (Path path in glyph.active_paths) { 265 s.append ("BF path: "); 266 s.append (BirdFontFile.get_point_data (path)); 267 s.append ("\n"); 268 269 s.append ("BF stroke: "); 270 s.append (@"$(path.stroke)"); 271 s.append ("\n"); 272 273 if (path.line_cap == LineCap.ROUND) { 274 s.append ("BF cap: round\n"); 275 } else if (path.line_cap == LineCap.SQUARE) { 276 s.append ("BF cap: square\n"); 277 } 278 } 279 } else { 280 new_path = new Path (); 281 foreach (Path path in glyph.get_visible_paths ()) { 282 if (path.points.size > 0 283 && path.points.get (0).is_selected () 284 && path.points.get (path.points.size - 1).is_selected ()) { 285 286 foreach (EditPoint ep in path.points) { 287 if (!ep.is_selected ()) { 288 path.set_new_start (ep); 289 break; 290 } 291 } 292 } 293 294 foreach (EditPoint ep in path.points) { 295 if (!ep.is_selected ()) { 296 if (path.points.size > 0) { 297 paths.add (new_path); 298 new_path = new Path (); 299 } 300 } else { 301 new_path.add_point (ep); 302 } 303 } 304 305 if (all_points_selected (path)) { 306 new_path.close (); 307 } 308 } 309 310 paths.add (new_path); 311 312 foreach (Path path in paths) { 313 if (path.points.size > 0) { 314 s.append ("BF path: "); 315 s.append (BirdFontFile.get_point_data (path)); 316 s.append ("\n"); 317 318 s.append ("BF stroke: "); 319 s.append (@"$(path.stroke)"); 320 s.append ("\n"); 321 322 if (path.line_cap == LineCap.ROUND) { 323 s.append ("BF cap: round\n"); 324 } else if (path.line_cap == LineCap.SQUARE) { 325 s.append ("BF cap: square\n"); 326 } 327 } 328 } 329 } 330 331 s.append ("BF end -->"); 332 } 333 334 return s.str; 335 } 336 337 static bool all_points_selected (Path p) { 338 foreach (EditPoint ep in p.points) { 339 if (!ep.is_selected ()) { 340 return false; 341 } 342 } 343 return true; 344 } 345 346 static void import_birdfont_clipboard (string data, bool paste_guide_lines, bool overview) { 347 Gee.ArrayList<GlyphCollection> glyphs = new Gee.ArrayList<GlyphCollection> (); 348 Glyph glyph = new Glyph ("null", '\0'); 349 string[] items = data.split ("\nBF "); 350 unichar c; 351 Glyph destination; 352 GlyphCollection glyph_collection = new GlyphCollection ('\0', ""); 353 OverView o; 354 Path path = new Path (); 355 356 foreach (string p in items) { 357 if (p.has_prefix ("glyph:")) { 358 p = p.replace ("glyph: ", ""); 359 p = p.replace ("\n", ""); 360 c = Font.to_unichar (p); 361 glyph_collection = new GlyphCollection (c, (!) c.to_string ()); 362 glyphs.add (glyph_collection); 363 364 glyph = new Glyph ((!) c.to_string (), c); 365 GlyphMaster master = new GlyphMaster (); 366 master.add_glyph (glyph); 367 glyph_collection.add_master (master); 368 } 369 370 if (p.has_prefix ("unassigned:")) { 371 p = p.replace ("unassigned: ", ""); 372 p = p.replace ("\n", ""); 373 glyph_collection.set_unassigned (bool.parse (p)); 374 } 375 376 if (p.has_prefix ("name:")) { 377 p = p.replace ("name: ", ""); 378 p = p.replace ("\n", ""); 379 glyph_collection.set_name (p); 380 glyph.name = p; 381 } 382 383 if (p.has_prefix ("path:")) { 384 p = p.replace ("path: ", ""); 385 p = p.replace ("\n", ""); 386 path = import_birdfont_path (glyph, p); 387 } 388 389 if (p.has_prefix ("left:")) { 390 glyph.left_limit = double.parse (p.replace ("left: ", "")); 391 glyph.remove_lines (); 392 glyph.add_help_lines (); 393 } 394 395 if (p.has_prefix ("right:")) { 396 glyph.right_limit = double.parse (p.replace ("right: ", "")); 397 glyph.remove_lines (); 398 glyph.add_help_lines (); 399 } 400 401 if (p.has_prefix ("stroke:")) { 402 path.stroke = double.parse (p.replace ("stroke: ", "")); 403 } 404 405 if (p.has_prefix ("cap:")) { 406 string cap = p.replace ("cap: ", ""); 407 408 if (cap == "round") { 409 path.line_cap = LineCap.ROUND; 410 } else if (cap == "square") { 411 path.line_cap = LineCap.SQUARE; 412 } 413 } 414 } 415 416 if (!overview) { 417 return_if_fail (glyphs.size > 0); 418 destination = MainWindow.get_current_glyph (); 419 glyph = glyphs.get (0).get_current (); 420 421 foreach (Path p in glyph.get_visible_paths ()) { 422 PenTool.clear_directions (); 423 destination.add_path (p); 424 destination.add_active_path (null, p); 425 } 426 427 if (paste_guide_lines) { 428 destination.left_limit = glyph.left_limit; 429 destination.right_limit = glyph.right_limit; 430 destination.add_help_lines (); 431 destination.update_other_spacing_classes (); 432 } 433 } else { 434 o = MainWindow.get_overview (); 435 o.copied_glyphs.clear (); 436 foreach (GlyphCollection gc in glyphs) { 437 o.copied_glyphs.add (gc); 438 } 439 o.paste (); 440 } 441 } 442 443 static Path import_birdfont_path (Glyph glyph, string data) { 444 Path path = new Path (); 445 446 BirdFontFile.parse_path_data (data, path); 447 448 if (path.points.size > 0) { 449 PenTool.clear_directions (); 450 glyph.add_path (path); 451 glyph.active_paths.add (path); 452 path.update_region_boundaries (); 453 } 454 455 PenTool.remove_all_selected_points (); 456 457 foreach (Path p in glyph.active_paths) { 458 if (p.is_open ()) { 459 foreach (EditPoint e in p.points) { 460 e.set_selected (true); 461 } 462 } 463 } 464 465 PenTool.update_selection (); 466 return path; 467 } 468 469 static void paste_letters_to_kerning_tab () { 470 string clipboard_data = MainWindow.native_window.get_clipboard_data (); 471 KerningDisplay kerning_display = MainWindow.get_kerning_display (); 472 473 if (!clipboard_data.has_prefix ("<?xml")) { 474 kerning_display.add_text (clipboard_data); 475 } 476 } 477 } 478 479 } 480