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