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