.
1 /*
2 Copyright (C) 2012 2014 2015 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 B;
16
17 namespace BirdFont {
18
19 public class ExportTool : GLib.Object {
20
21 public ExportTool (string n) {
22 }
23
24 public static string export_selected_paths_to_svg () {
25 return export_current_glyph_to_string (true);
26 }
27
28 public static string export_selected_paths_to_inkscape_clipboard () {
29 return export_current_glyph_to_inkscape_clipboard (true);
30 }
31
32 public static string export_current_glyph_to_string (bool only_selected_paths = false) {
33 return export_to_string (MainWindow.get_current_glyph (), only_selected_paths);
34 }
35
36 public static string export_to_string (Glyph glyph, bool only_selected_paths) {
37 string name;
38 StringBuilder s;
39
40 name = XmlParser.encode (glyph.get_name ());
41 s = new StringBuilder ();
42
43 s.append ("""<?xml version="1.0" encoding="utf-8"?>
44 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
45 <svg version="1.0"
46 id="glyph_""" + name + """"
47 mlns="http://www.w3.org/2000/svg"
48 xmlns:xlink="http://www.w3.org/1999/xlink"
49 x="0px"
50 y="0px"
51 width=""" + "\"" + @"$(glyph.get_width ())" + """px"
52 height=""" + "\"" + @"$(glyph.get_height ())" + """px">
53 """);
54
55 s.append (@"<g id=\"$(name)\">\n");
56
57 s.append (get_svg_path_elements (glyph, only_selected_paths));
58
59 s.append ("</g>\n");
60 s.append ("</svg>");
61
62 return s.str;
63 }
64
65 public static string export_current_glyph_to_inkscape_clipboard (bool only_selected_paths = false) {
66 return export_to_inkscape_clipboard (MainWindow.get_current_glyph (), only_selected_paths);
67 }
68
69 public static string export_to_inkscape_clipboard (Glyph glyph, bool only_selected_paths = false) {
70 StringBuilder s;
71
72 s = new StringBuilder ();
73 s.append ("""<?xml version="1.0" encoding="UTF-8" standalone="no"?>""");
74 s.append ("\n");
75 s.append ("<svg>\n");
76
77 s.append ("""<inkscape:clipboard
78 id="clipboard3009"
79 style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
80 min="0,0"
81 max="0,0" />
82 """);
83
84 s.append (get_svg_path_elements (glyph, only_selected_paths));
85 s.append ("</svg>");
86
87 return s.str;
88 }
89
90 private static string get_svg_path_elements (Glyph glyph, bool only_selected_paths) {
91 string glyph_svg;
92 StringBuilder s;
93 string name;
94 int id = 0;
95
96 name = glyph.get_name ();
97
98 Gee.ArrayList<Path> pl;
99
100 s = new StringBuilder ();
101 glyph_svg = "";
102
103 pl = only_selected_paths ? glyph.active_paths : glyph.get_visible_paths ();
104 foreach (Path p in pl) {
105 if (p.stroke > 0) {
106 s.append (@"<path ");
107 s.append (@"style=\"");
108 s.append (@"fill:none;");
109 s.append (@"stroke:#000000;");
110 s.append (@"stroke-width:$(p.stroke)px;");
111
112 if (p.line_cap == LineCap.ROUND) {
113 s.append (@"stroke-linecap:round;");
114 } else if (p.line_cap == LineCap.SQUARE) {
115 s.append (@"stroke-linecap:square;");
116 }
117
118 s.append (@"\" ");
119
120 s.append (@"d=\"$(Svg.to_svg_path (p, glyph))\" id=\"path_$(name)_$(id)\" />\n");
121 id++;
122 }
123 }
124
125 if (only_selected_paths) {
126 foreach (Path p in glyph.active_paths) {
127 if (p.stroke == 0) {
128 glyph_svg += Svg.to_svg_path (p, glyph);
129 }
130 }
131 } else {
132 foreach (Path p in glyph.get_visible_paths ()) {
133 if (p.stroke == 0) {
134 glyph_svg += Svg.to_svg_path (p, glyph);
135 }
136 }
137 }
138
139 if (glyph_svg != "") {
140 s.append (@"<path ");
141 s.append (@"style=\"fill:#000000;stroke-width:0px\" ");
142 s.append (@"d=\"$(glyph_svg)\" id=\"path_$(name)_$(id)\" />\n");
143 id++;
144 }
145
146 return s.str;
147 }
148
149 public static void export_current_glyph () {
150 FileChooser fc = new FileChooser ();
151 fc.file_selected.connect ((selected_file) => {
152 Glyph glyph = MainWindow.get_current_glyph ();
153 FontDisplay fd = MainWindow.get_current_display ();
154 string glyph_svg;
155 string svg_file;
156 File file;
157 DataOutputStream os;
158 string name;
159 string fn;
160 int i;
161
162 if (fd is Glyph) {
163 glyph = MainWindow.get_current_glyph ();
164 } else if (fd is OverView) {
165 OverView overview = MainWindow.get_overview ();
166 Glyph? g = overview.get_selected_glyph ();
167
168 if (g == null) {
169 warning("No glyhp selected in overview.");
170 return;
171 }
172
173 glyph = (!) g;
174 } else {
175 return;
176 }
177
178 name = glyph.get_name ();
179
180 if (selected_file == null) {
181 return;
182 }
183
184 svg_file = (!) selected_file;
185
186 try {
187 #if MAC
188 file = File.new_for_path (svg_file);
189 #else
190 i = 1;
191 fn = svg_file.replace (".svg", "");
192 file = File.new_for_path (fn + ".svg");
193 while (file.query_exists ()) {
194 file = File.new_for_path (fn + @"$i.svg");
195 i++;
196 }
197 #endif
198 glyph_svg = export_to_string (glyph, false);
199 os = new DataOutputStream (file.create(FileCreateFlags.REPLACE_DESTINATION));
200 os.put_string (glyph_svg);
201
202 } catch (Error e) {
203 stderr.printf (@"Export \"$svg_file\" \n");
204 critical (@"$(e.message)");
205 }
206 });
207
208 fc.add_extension ("svg");
209 MainWindow.file_chooser (t_("Save"), fc, FileChooser.SAVE);
210 }
211
212 public static void generate_html_document (string html_file, Font font) {
213 File file = File.new_for_path (html_file);
214 DataOutputStream os;
215 string name;
216
217 #if MAC
218 name = ExportSettings.get_file_name_mac (font);
219 #else
220 name = ExportSettings.get_file_name (font);
221 #endif
222 try {
223 os = new DataOutputStream (file.create(FileCreateFlags.REPLACE_DESTINATION));
224
225 os.put_string (
226 """<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
227 <html>
228 <head>
229
230 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
231 <title>Lorem ipsum</title>
232
233 <style type="text/css">
234
235 body {
236 text-rendering: optimizeLegibility;
237 font-feature-settings: "kern";
238 -moz-font-feature-settings: "kern=1";
239 -ms-font-feature-settings: "kern";
240 -webkit-font-feature-settings: "kern";
241 -o-font-feature-settings: "kern";
242 }
243
244 @font-face {
245 font-family: '"""); os.put_string (@"$(name)"); os.put_string ("""SVG';
246 src: url('"""); os.put_string (@"$(name).svg#$(name)"); os.put_string ("""') format('svg');
247 }
248 """);
249
250 os.put_string ("""
251 @font-face {
252 font-family: '"""); os.put_string (@"$(name)"); os.put_string ("""TTF';
253 src: url('"""); os.put_string (@"$(name).ttf"); os.put_string ("""') format('truetype');
254 }
255 """);
256
257 os.put_string ("""
258 @font-face {
259 font-family: '"""); os.put_string (@"$(name)"); os.put_string ("""EOT';
260 src: url('"""); os.put_string (@"$(name).eot"); os.put_string ("""');
261 }
262
263 """);
264
265 os.put_string ("""
266 h1 {
267 font-weight:normal;
268 margin: 0 0 5px 0;
269 color: #afafaf;
270 }
271
272 h2 {
273 font-weight:normal;
274 margin: 0 0 5px 0;
275 color: #afafaf;
276 }
277
278 h3 {
279 font-weight:normal;
280 margin: 0 0 5px 0;
281 color: #afafaf;
282 }
283
284 h4 {
285 font-weight:normal;
286 margin: 0 0 5px 0;
287 color: #afafaf;
288 }
289
290 p {
291 margin: 0 0 5px 0;
292 color: #000000;
293 }
294
295 body {
296 margin: 30px 0 0 30px;
297 }
298
299 div {
300 font-family: """);
301
302 os.put_string ("'");
303 os.put_string (@"$(name)");
304 os.put_string ("EOT'");
305
306 os.put_string (", '");
307 os.put_string (@"$(name)");
308 os.put_string ("TTF'");
309
310 os.put_string (", '");
311 os.put_string (@"$(name)");
312 os.put_string ("SVG'");
313
314 os.put_string (";");
315 os.put_string ("""
316 margin: 0 0 30px 0;
317 }
318
319 h1.bigger {
320 font-size: 58pt;
321 }
322
323 h2.big {
324 font-size: 40pt;
325 }
326
327 h3.small {
328 font-size: 32pt;
329 }
330
331 h4.smaller {
332 font-size: 18pt;
333 }
334
335 h1.percent {
336 font-size: 100%;
337 }
338
339 p.bigger {
340 font-size: 32pt;
341 }
342
343 p.big {
344 font-size: 24pt;
345 }
346
347 p.small {
348 font-size: 18pt;
349 }
350
351 p.smaller {
352 font-size: 12pt;
353 }
354
355 span.swashes {
356 -moz-font-feature-settings: "swsh";
357 -ms-font-feature-settings: "swsh";
358 -webkit-font-feature-settings: "swsh";
359 font-feature-settings: "swsh";
360 }
361
362 span.alternates {
363 -moz-font-feature-settings: "salt" 1;
364 -ms-font-feature-settings: "salt" 1;
365 -webkit-font-feature-settings: "salt" 1;
366 font-feature-settings: "salt" 1;
367 }
368
369 span.smallcaps {
370 font-variant-caps: small-caps;
371 -moz-font-feature-settings: "smcp";
372 -ms-font-feature-settings: "smcp";
373 -webkit-font-feature-settings: "smcp";
374 font-feature-settings: "smcp";
375 }
376
377 span.capstosmallcaps {
378 font-variant-caps: all-small-caps;
379 -moz-font-feature-settings: "c2sc", "smcp";
380 -ms-font-feature-settings: "c2sc", "smcp";
381 -webkit-font-feature-settings: "c2sc", "smcp";
382 font-feature-settings: "c2sc", "smcp";
383 }
384 </style>
385 """);
386
387 os.put_string (
388 """
389 </head>
390 <body>
391
392 <div>
393 <h1 class="bigger">Lorem ipsum</h1>
394 <p class="bigger">Dolor sit amet!</p>
395 </div>
396
397 <div>
398 <h2 class="big">Hamburgerfonstiv</h2>
399 <p class="big">""" + name + """</p>
400 </div>
401
402 <div>
403 <h3 class="big"></h3>
404 <p class="big">
405 <span class="capstosmallcaps">OTF</span> features,
406 <span class="swashes">like swashes </span>
407 <span class="alternates">alternates & </span>
408 <span class="smallcaps">small caps</span>, can be added
409 to the font.</span>
410 </p>
411 </div>
412
413 <div>
414 <h4 class="smaller">Headline 16pt</h4>
415 <p class="smaller">Ett litet stycke svalhjärta.</p>
416 </div>
417
418 <div>
419 <h4 class="smaller">""" + t_("Alphabet") + """</h4>
420 <p class="smaller">""" + t_("a b c d e f g h i j k l m n o p q r s t u v w x y z") + """</p>
421 <p class="smaller">""" + t_("A B C D E F G H I J K L M N O P Q R S T U V W X Y Z") + """</p>
422 <p class="smaller">0 1 2 3 4 5 6 7 8 9</p>
423 </div>
424
425 </body>
426 </html>
427 """);
428
429 } catch (GLib.Error e) {
430 warning (e.message);
431 }
432 }
433
434 public static string get_export_folder () {
435 Font font = BirdFont.get_current_font ();
436 string? sandbox = BirdFont.get_sandbox_directory ();
437
438 if (sandbox != null) {
439 File s = File.new_for_path ((!) sandbox);
440 File f = get_child (s, "Fonts");
441 try {
442 if (!f.query_exists ()) {
443 f.make_directory ();
444 }
445 } catch (GLib.Error e) {
446 warning(e.message);
447 }
448 return (!) get_child (f, font.full_name).get_path ();
449 } else {
450 return (!) font.get_folder ().get_path ();
451 }
452 }
453
454 public static File get_export_dir () {
455 return File.new_for_path (get_export_folder ());
456 }
457
458 public static bool export_ttf_font () {
459 File f = get_export_dir ();
460 Font font = BirdFont.get_current_font ();
461
462 try {
463 if (!f.query_exists ()) {
464 f.make_directory ();
465 }
466 } catch (GLib.Error e) {
467 warning(e.message);
468 }
469
470 printd (@"export_ttf_font:\n");
471 printd (@"get_export_folder (): $(get_export_folder ())\n");
472 printd (@"font.get_path (): $(font.get_path ())\n");
473 printd (@"font.get_folder_path (): $(font.get_folder_path ())\n");
474 printd (@"font.get_folder (): $((!) f.get_path ())\n");
475
476 return export_ttf_font_path (f);
477 }
478
479 public static bool export_ttf_font_path (File folder, bool use_export_settings = true) {
480 Font current_font = BirdFont.get_current_font ();
481 File ttf_file;
482 File ttf_file_mac;
483 File eot_file;
484 bool done = true;
485 string ttf_name;
486 string ttf_name_mac;
487
488 try {
489 ttf_name = ExportSettings.get_file_name (current_font) + ".ttf";
490 ttf_name_mac = ExportSettings.get_file_name_mac (current_font) + ".ttf";
491
492 if (ttf_name == ttf_name_mac) {
493 warning ("Same file name for the two ttf files.");
494 ttf_name_mac = ExportSettings.get_file_name_mac (current_font) + " Mac.ttf";
495 }
496
497 ttf_file = get_child (folder, ttf_name);
498 ttf_file_mac = get_child (folder, ttf_name_mac);
499 eot_file = get_child (folder, ExportSettings.get_file_name (current_font) + ".eot");
500
501 printd (@"Writing TTF fonts to $((!) ttf_file.get_path ())\n");
502
503 if (ttf_file.query_exists ()) {
504 ttf_file.delete ();
505 }
506
507 if (ttf_file_mac.query_exists ()) {
508 ttf_file_mac.delete ();
509 }
510
511 if (eot_file.query_exists ()) {
512 eot_file.delete ();
513 }
514
515 write_ttf ((!) ttf_file.get_path (), (!) ttf_file_mac.get_path ());
516
517 if (!use_export_settings || ExportSettings.export_eot_setting (current_font)) {
518 write_eot ((!) ttf_file.get_path (), (!) eot_file.get_path ());
519 }
520
521 if (use_export_settings && !ExportSettings.export_ttf_setting (current_font)) {
522 if (ttf_file.query_exists ()) {
523 ttf_file.delete ();
524 }
525 }
526 } catch (Error e) {
527 critical (@"$(e.message)");
528 done = false;
529 }
530
531 return done;
532 }
533
534 public static bool export_svg_font () {
535 return export_svg_font_path (get_export_dir ());
536 }
537
538 public static bool export_svg_font_path (File folder) {
539 Font font = BirdFont.get_current_font ();
540 string file_name = @"$(ExportSettings.get_file_name (font)).svg";
541 File file;
542 SvgFontFormatWriter fo;
543
544 try {
545 file = get_child (folder, file_name);
546
547 if (file.query_exists ()) {
548 file.delete ();
549 }
550
551 fo = new SvgFontFormatWriter ();
552 fo.open (file);
553 fo.write_font_file (font);
554 fo.close ();
555 } catch (Error e) {
556 critical (@"$(e.message)");
557 return false;
558 }
559
560 return true;
561 }
562
563 static void write_ttf (string ttf, string ttf_mac) {
564 Font f = BirdFont.get_current_font ();
565 OpenFontFormatWriter fo = new OpenFontFormatWriter (f.units_per_em);
566
567 File file = (!) File.new_for_path (ttf);
568 File file_mac = (!) File.new_for_path (ttf_mac);
569
570 try {
571 fo.open (file, file_mac);
572 fo.write_ttf_font (f);
573 fo.close ();
574 } catch (Error e) {
575 warning (@"Can't write TTF font to $ttf");
576 critical (@"$(e.message)");
577 }
578 }
579
580 static void write_eot (string ttf, string eot) {
581 EotWriter fo = new EotWriter (ttf, eot);
582
583 try {
584 fo.write ();
585 } catch (Error e) {
586 warning (@"EOF conversion falied, $ttf -> $eot");
587 critical (@"$(e.message)");
588 }
589 }
590 }
591
592 }
593