.
1 /*
2 Copyright (C) 2012, 2013, 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 using Bird;
16
17 namespace BirdFont {
18
19 /** All the things we want to test listed is here. */
20 class TestCases {
21
22 public List<Test> test_cases;
23
24 public TestCases () {
25 add (test_overview, "Overview");
26 add (test_data_reader, "Font data reader");
27 add (test_argument, "Argument list");
28 add (test_glyph_ranges, "Glyph ranges");
29 add (test_hex, "Unicode hex values");
30 add (test_reverse_path, "Reverse path");
31 add (test_reverse_random_triangles, "Reverse random paths");
32 add (test_coordinates, "Coordinates");
33 add (test_drawing, "Pen tool");
34 add (test_delete_points, "Delete edit points");
35 add (test_convert_to_quadratic_bezier_path, "Convert to quadratic path");
36 add (test_over_path, "Over path");
37 add (test_export, "Export");
38 add (test_background_coordinates, "Background coordinates");
39 add (test_spin_button, "Spin button");
40 add (test_inkscape_import, "Inkscape import");
41 add (test_illustrator_import, "Illustrator import");
42 add (test_parse_quadratic_paths, "Quadratic paths");
43 add (test_freetype, "Freetype");
44 add (test_preview, "Preview");
45 add (test_kerning, "Kerning");
46 add (test_boundaries, "Boundaries");
47 add (test_extrema, "Extrema");
48 add (test_codepages, "Codepages");
49 add (test_double_quadratic, "Double quadratic");
50 add (test_raster_path, "Raster path");
51 add (test_file_path, "File path");
52 add (test_xml, "XML");
53
54 add_bechmark (benchmark_stroke, "Stroke");
55 }
56
57 private void add_bechmark (Callback callback, string name) {
58 test_cases.append (new Test (callback, name, true));
59 }
60
61 private void add (Callback callback, string name) {
62 test_cases.append (new Test (callback, name));
63 }
64
65 public unowned List<Test> get_test_functions () {
66 return test_cases;
67 }
68
69 public static void test_double_quadratic () {
70 Glyph g = MainWindow.get_current_glyph ();
71 Gee.ArrayList<Path> paths = new Gee.ArrayList<Path> ();
72 Path pn;
73
74 foreach (Path p in g.path_list) {
75 pn = p.copy ();
76 pn.add_hidden_double_points ();
77 paths.add (pn);
78 }
79
80 foreach (Path p in paths) {
81 g.add_path (p);
82 }
83 }
84
85 public static void test_codepages () {
86 CodePageBits pages = new CodePageBits ();
87
88 if (pages.get_bits ('ó').size == 0) {
89 warning ("Codepage for Hungarian is not set.");
90 }
91
92 if (pages.get_bits ('ö').size == 0) {
93 warning ("Codepage for Swedish is not set.");
94 }
95
96 if (pages.get_bits ('ツ').size == 0) {
97 warning ("Codepage for Japanese is not set.");
98 }
99
100 if (pages.get_bits ('马').size == 0) {
101 warning ("Codepage for Chinese is not set.");
102 }
103 }
104
105 public static void load_test_font () {
106 string fn = "./fonts/Decibel.bf";
107 Font f = BirdFont.new_font ();
108
109 f.set_read_only (true);
110
111 f.set_file (fn);
112 if (!f.load ()) {
113 warning (@"Failed to load fond $fn");
114 return;
115 }
116
117 if (f.length () == 0) {
118 warning ("No glyphs in font.");
119 }
120 }
121
122 public static void test_kerning () {
123 KerningDisplay k;
124 Font font;
125 Glyph? g;
126
127 load_test_font ();
128
129 k = MainWindow.get_kerning_display ();
130 font = BirdFont.get_current_font ();
131 MenuTab.show_kerning_context ();
132
133 if (font.length () == 0) {
134 warning ("No font loaded.");
135 }
136
137 for (int i = 0; i < 10; i++) {
138 for (int j = 0; j < 10; j++) {
139 g = font.get_glyph_indice (Random.int_range (0, (int) font.length () - 1));
140 return_if_fail (g != null);
141 if (Random.int_range (1, 9) % 3 == 0) {
142 k.add_kerning_class (Random.int_range (0, 9));
143 } else {
144 k.add_text (((!)g).get_unichar_string ());
145 }
146
147 GlyphCanvas.redraw ();
148 Tool.yield ();
149 }
150
151 for (int j = 0; j < 10; j++) {
152 k.set_absolute_kerning (Random.int_range (1, 9), Random.int_range (0, 30));
153 GlyphCanvas.redraw ();
154 Tool.yield ();
155 }
156
157 k.new_line ();
158 GlyphCanvas.redraw ();
159 Tool.yield ();
160 }
161 }
162
163 public static void benchmark_stroke () {
164 Glyph glyph;
165 test_open_next_glyph ();
166 test_illustrator_import ();
167
168 glyph = MainWindow.get_current_glyph ();
169 for (int i = 0; i < 5; i++) {
170 foreach (Path p in glyph.path_list) {
171 p.set_stroke (i / 100.0);
172 glyph.update_view ();
173 Tool.yield ();
174 }
175 }
176 }
177
178 public static void test_extrema () {
179 Glyph g;
180 SvgParser parser = new SvgParser ();
181
182 test_open_next_glyph ();
183 g = MainWindow.get_current_glyph ();
184
185 parser.set_format (SvgFormat.INKSCAPE);
186 parser.add_path_to_glyph ("m -163.59375,-250.78125 c -42.43208,51.5679 -78.92929,123.30265 -109.59375,216.03125 l 94.9375,31.375 c 27.9767,-84.600883 60.86301,-146.18598 91.875,-183.875 48.545803,-62.79748 104.513616,-52.47212 139.34375,-5.46875 25.619399,35.30837 51.38402,95.22476 69.625,178.625 l 97.6875,-21.375 c -20.20842,-92.39565 -48.64621,-164.00261 -86.375,-216 -88.811818,-115.9163 -218.868232,-92.82539 -297.5,0.6875 z", g);
187
188 Toolbox.select_tool_by_name ("full_glyph");
189
190 foreach (Path p in g.path_list) {
191 p.add_extrema ();
192 }
193 }
194
195 public static void test_freetype () {
196 StringBuilder? data;
197 int error;
198 File f = BirdFont.get_settings_directory ();
199 Font font = BirdFont.get_current_font ();
200
201 font.set_name ("TEST_FONT");
202
203 // draw some test glyphs
204 test_illustrator_import ();
205 test_inkscape_import ();
206
207 Tool.yield ();
208
209 if (!ExportTool.export_ttf_font_path (f)) {
210 warning ("TTF export failed.");
211 }
212
213 f = get_child (f, font.get_name () + ".ttf");
214 if (!f.query_exists ()) {
215 warning ("File does not exist.");
216 }
217
218 data = load_freetype_font ((!) f.get_path (), out error);
219 if (error != 0) {
220 warning ("Failed to load font.");
221 return;
222 }
223
224 if (data == null) {
225 warning ("No bf data.");
226 return;
227 }
228
229 Tool.yield ();
230 font.load ();
231 }
232
233 public static void test_parse_quadratic_paths () {
234 Glyph g;
235 SvgParser parser = new SvgParser ();
236
237 test_open_next_glyph ();
238
239 parser.set_format (SvgFormat.INKSCAPE);
240
241 g = MainWindow.get_current_glyph ();
242 parser.parse_svg_data ("M20,300 Q400,50 600,300 T1000,300Q1200 50 1400 300Q1600 50 1800 600 L 1800 700 L 200 700 z", g);
243 Toolbox.select_tool_by_name ("full_glyph");
244
245 g = MainWindow.get_current_glyph ();
246 parser.parse_svg_data ("M300 400 h-200 l0 1000 h200z", g, true);
247 Toolbox.select_tool_by_name ("full_glyph");
248
249
250 parser.set_format (SvgFormat.ILLUSTRATOR);
251
252 g = MainWindow.get_current_glyph ();
253 parser.parse_svg_data ("M20,300 Q400,50 600,300 T1000,300Q1200 50 1400 300Q1600 50 1800 600 L 1800 700 L 200 700 z", g);
254 Toolbox.select_tool_by_name ("full_glyph");
255
256 g = MainWindow.get_current_glyph ();
257 parser.parse_svg_data ("M300 400 h-200 l0 1000 h200z", g, true);
258 Toolbox.select_tool_by_name ("full_glyph");
259
260 }
261
262 public static void test_illustrator_import () {
263 Glyph g;
264 SvgParser parser = new SvgParser ();
265 string illustrator_data = """<?xml version="1.0" encoding="utf-8"?>
266 <!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
267 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
268 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
269 width="595.28px" height="841.89px" viewBox="0 0 595.28 841.89" enable-background="new 0 0 595.28 841.89" xml:space="preserve">
270 <path fill="#FFFFFF" stroke="#000000" stroke-miterlimit="10" d="M49.102,263.776"/>
271 <g>
272 <g>
273 <path d="M3.037,3.799c0.006-0.057,0.013-0.114,0.019-0.171c0.111-1.002-1.577-0.438-1.89,0.01c0.007-0.012,0.013-0.024,0.02-0.036
274 C1.49,3.626,1.795,3.651,2.1,3.676C2.061,3.954,2.195,4.022,2.5,3.88c0.346-0.007,0.691-0.009,1.036-0.006
275 C4.45,3.876,5.367,3.971,6.279,4.015c1.569,0.075,3.033-0.056,4.441-0.776c1.18-0.604,0.111-1.501-0.824-1.022
276 c-2.19,1.121-5.157,0.242-7.563,0.39C1.281,2.67,0.104,3.19,0.182,4.371C0.218,4.488,0.29,4.577,0.395,4.639
277 C1.397,5.095,2.39,4.668,2.997,3.797c-0.63,0.003-1.26,0.006-1.89,0.01C1.101,3.864,1.095,3.921,1.088,3.979
278 C0.985,4.903,2.948,4.596,3.037,3.799L3.037,3.799z"/>
279 </g>
280 </g>
281 <g>
282 <g>
283 <path d="M4.668,3.559C4.614,5.102,4.586,6.642,4.63,8.186c0.02,0.679-0.033,1.363-0.054,2.041
284 c-0.017,0.587,0.309,1.136-0.299,1.16c-0.563,0.022-1.708,1.045-0.669,1.263c1.091,0.229,2.12,0.154,3.229,0.118
285 c1.057-0.035,1.522-1.348,0.201-1.305c-0.76,0.025-1.539,0.124-2.293-0.035c-0.223,0.421-0.446,0.842-0.669,1.263
286 c1.091-0.043,2.411-0.278,2.5-1.583c0.173-2.551-0.048-5.164,0.042-7.728C6.65,2.432,4.696,2.761,4.668,3.559L4.668,3.559z"/>
287 </g>
288 </g>
289 <g>
290 <g>
291 <path d="M10.014,7.024C9.189,7.82,8.786,8.42,8.661,9.58c-0.098,0.906-0.05,1.599,0.515,2.346
292 c1.215,1.608,3.572,0.777,5.021,0.102c0.216-0.101,0.627-0.469,0.208-0.612c-0.437-0.149-0.964,0.034-1.358,0.218
293 c-1.281,0.597-2.335-0.241-2.516-1.55C10.356,8.81,10.916,7.8,11.784,6.961c0.336-0.325-0.288-0.434-0.486-0.427
294 C10.843,6.55,10.346,6.704,10.014,7.024L10.014,7.024z"/>
295 </g>
296 </g>
297 <g>
298 <g>
299 <path d="M11.415,7.436c0.267-0.022,0.588-0.066,0.852,0.006c-0.072-0.02-0.12-0.251-0.072-0.044
300 c0.021,0.091-0.01,0.268-0.007,0.372c0.003,0.135,0.007,0.264-0.003,0.399c0.001-0.022,0.038-0.029-0.014-0.024
301 c-0.343,0.036-0.735,0.108-1.079,0.09c-0.478-0.026-1.041,0.124-1.254,0.606c-0.187,0.423,0.169,0.847,0.604,0.87
302 c1.314,0.07,3.575-0.07,3.716-1.796c0.043-0.535,0.063-1.19-0.354-1.581c-0.544-0.511-1.554-0.451-2.239-0.394
303 c-0.441,0.037-1.006,0.31-1.056,0.81C10.459,7.24,11.007,7.47,11.415,7.436L11.415,7.436z"/>
304 </g>
305 </g>
306 <g>
307 <g>
308 <path d="M17.85,6.628c-0.13,0.059-0.265,0.102-0.404,0.131c0.104-0.019,0.122-0.021,0.051-0.008
309 c0.112-0.013,0.218-0.015,0.33-0.013c0.152,0.002,0.394,0.013,0.466,0.17c0.207,0.454,2.073-0.208,1.932-0.518
310 c-0.203-0.445-0.951-0.422-1.354-0.417c-0.719,0.01-1.468,0.13-2.126,0.43c-0.143,0.065-0.675,0.39-0.243,0.477
311 C16.934,6.969,17.461,6.806,17.85,6.628L17.85,6.628z"/>
312 </g>
313 </g>
314 <g>
315 <g>
316 <path d="M16.858,6.049c-1.111,0.292-2.424,1.692-1.018,2.544c1.076,0.653,3.576,0.595,2.513,2.572
317 c-0.206,0.382,0.683,0.367,0.816,0.348c0.419-0.059,0.897-0.228,1.107-0.619c0.548-1.019,0.155-1.903-0.79-2.432
318 c-0.418-0.234-0.906-0.356-1.363-0.491c-0.251-0.075-0.492-0.155-0.732-0.259c-0.302-0.131-0.08-0.863-0.304-0.804
319 c0.242-0.063,0.952-0.313,0.851-0.688C17.838,5.842,17.1,5.985,16.858,6.049L16.858,6.049z"/>
320 </g>
321 </g>
322 <g>
323 <g>
324 <path d="M14.983,10.708c-0.036,0.299-0.137,0.716,0.08,0.972c0.244,0.286,0.663,0.358,1.01,0.435
325 c0.994,0.221,1.846,0.177,2.792-0.243c0.185-0.082,0.844-0.417,0.533-0.711c-0.296-0.28-0.951-0.124-1.269,0.018
326 c-0.317,0.141-0.505,0.035-0.853-0.039c-0.444-0.095-0.42-0.276-0.369-0.702C16.991,9.74,15.055,10.114,14.983,10.708
327 L14.983,10.708z"/>
328 </g>
329 </g>
330 <g>
331 <g>
332 <path d="M21.915,6.956c1.207,0.189,2.389,0.085,3.601,0.082c0.424-0.001,1.009-0.321,1.063-0.784
333 c0.06-0.506-0.514-0.641-0.895-0.639c-1.048,0.003-2.059,0.093-3.103-0.071C21.625,5.394,20.618,6.752,21.915,6.956L21.915,6.956z
334 "/>
335 </g>
336 </g>
337 <g>
338 <g>
339 <path d="M21.948,5.359c-0.002,1.245-0.005,2.491-0.045,3.735c-0.023,0.708-0.252,1.594,0.142,2.241
340 c0.911,1.494,3.401,0.492,4.227-0.546c0.544-0.685-1.407-0.547-1.802-0.051c-0.708,0.891-0.653-1.618-0.634-1.881
341 c0.087-1.235,0.043-2.497,0.045-3.735C23.883,4.302,21.949,4.715,21.948,5.359L21.948,5.359z"/>
342 </g>
343 </g>
344 </svg>""";
345 try {
346 File temp_file;
347 FileIOStream? ios;
348 DataOutputStream d;
349 FileOutputStream? os;
350
351 temp_file = get_child (BirdFont.get_settings_directory (), "illustrator_test.svg");
352
353 if (temp_file.query_exists ()) {
354 temp_file.delete ();
355 }
356
357 ios = temp_file.create_readwrite (FileCreateFlags.PRIVATE);
358 os = ((!) ios).output_stream as FileOutputStream?;
359 d = new DataOutputStream ((!) os);
360
361 d.put_string (illustrator_data);
362 d.close ();
363
364 test_open_next_glyph ();
365 SvgParser.import_svg ((!) temp_file.get_path ());
366
367 temp_file.delete ();
368
369 g = MainWindow.get_current_glyph ();
370
371 parser.set_format (SvgFormat.ILLUSTRATOR);
372 parser.add_path_to_glyph ("M67.4,43.5c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2c0-1.1,0.9-2,2-2C66.5,41.5,67.4,42.4,67.4,43.5z", g);
373
374 Toolbox.select_tool_by_name ("full_glyph");
375 } catch (GLib.Error e) {
376 warning (e.message);
377 }
378 }
379
380 public static void test_inkscape_import () {
381 string inkscape_data = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
382 <svg
383 xmlns:dc="http://purl.org/dc/elements/1.1/"
384 xmlns:cc="http://creativecommons.org/ns#"
385 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
386 xmlns:svg="http://www.w3.org/2000/svg"
387 xmlns="http://www.w3.org/2000/svg"
388 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
389 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
390 width="56"
391 height="111"
392 id="glyph_A"
393 version="1.1"
394 inkscape:version="0.48.2 r9819"
395 sodipodi:docname="Glyph_template.svg">
396 <metadata
397 id="metadata10">
398 <rdf:RDF>
399 <cc:Work
400 rdf:about="">
401 <dc:format>image/svg+xml</dc:format>
402 <dc:type
403 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
404 <dc:title></dc:title>
405 </cc:Work>
406 </rdf:RDF>
407 </metadata>
408 <defs
409 id="defs8" />
410 <sodipodi:namedview
411 id="namedview3"
412 showgrid="false"
413 inkscape:zoom="1"
414 inkscape:cx="-27.517479"
415 inkscape:cy="43.414876"
416 inkscape:window-width="721"
417 inkscape:window-height="429"
418 inkscape:window-x="557"
419 inkscape:window-y="24"
420 inkscape:window-maximized="0"
421 inkscape:current-layer="glyph_A"
422 inkscape:object-paths="true">
423 <sodipodi:guide
424 orientation="0,1"
425 position="0,39"
426 id="baseline" />
427 </sodipodi:namedview>
428 <path
429 style="fill:#000000;fill-opacity:1;stroke:none"
430 id="path3142"
431 d="M 2.4461236,18.613363 C 3.4535706,17.30804 4.565697,16.070157 5.7189269,14.889064 9.7698153,10.543221 17.324067,7.5616696 21.327378,5.1981153 25.286661,2.860555 13.350954,9.773823 9.3627418,12.061677 16.280624,7.4352732 19.834614,4.1353939 26.808001,3.7441018 c 1.967367,-0.074299 3.936743,-0.05736 5.905091,-0.051608 1.741423,0.3127973 3.428071,0.6890467 5.085162,1.2943721 1.392556,0.6843074 2.448976,1.7917908 3.622959,2.766069 1.120096,1.0121812 2.001523,2.1988012 2.819774,3.4625798 0.849867,1.417783 1.525325,2.83856 1.899606,4.455126 0.609221,1.591091 0.969893,3.232962 1.176184,4.91949 0.18844,1.961102 0.190368,3.933599 0.19931,5.901817 -0.02338,1.98962 0.05666,3.98236 -0.06167,5.96929 -0.326157,1.726864 -0.640714,3.446402 -0.799219,5.198174 -0.141202,1.943199 -0.145653,3.892792 -0.153936,5.840056 -0.0035,2.000837 7.65e-4,4.001679 0.0028,6.002516 0.0019,2.000867 0.0023,4.001735 0.0026,6.002602 -0.119448,1.837413 0.05012,3.609162 0.411903,5.404108 0.436533,1.339043 1.162712,2.583413 2.144788,3.594149 1.406807,1.142779 3.002396,1.683088 4.761485,1.987684 1.194717,0.02857 2.577648,0.517596 3.736705,0.02255 0.232429,-0.09927 0.843546,-0.555586 0.622914,-0.432299 -4.033997,2.254157 -8.043973,4.551038 -12.065959,6.826557 0.179915,-0.145379 0.359829,-0.290757 0.539744,-0.436135 0,0 13.621702,-5.579012 13.621702,-5.579012 l 0,0 c -0.167578,0.175551 -0.335155,0.351102 -0.502733,0.526654 -8.740107,5.12179 -10.300507,8.97968 -17.955597,7.404265 -1.957383,-0.50948 -3.799128,-1.304798 -5.299977,-2.701355 -1.123481,-1.261267 -2.039019,-2.666586 -2.534331,-4.296084 -0.383149,-1.891076 -0.646571,-3.750061 -0.493931,-5.690321 -1.27e-4,-2.000559 -2.84e-4,-4.001119 -0.0017,-6.001678 -0.0017,-2.002107 -0.0049,-4.004212 -0.0062,-6.00632 0.0014,-1.974097 -0.0026,-3.949232 0.08455,-5.921848 0.102996,-1.775437 0.264342,-3.552014 0.742963,-5.2725 0.434483,-1.889017 0.07193,-3.87962 0.190989,-5.804901 -0.0055,-1.914254 -0.0023,-3.8318 -0.157754,-5.741122 -0.175482,-1.642594 -0.511621,-3.23618 -1.128362,-4.775955 -0.299347,-1.455042 -0.914171,-2.699067 -1.678627,-3.966466 -0.757218,-1.14089 -1.561752,-2.21279 -2.610877,-3.106654 -1.010538,-0.897967 -2.015327,-1.827459 -3.298779,-2.322908 -1.523105,-0.512447 -3.13219,-0.816768 -4.732721,-0.938511 -1.950528,0.0034 -3.90631,-0.0079 -5.849616,0.18331 C 9.3832464,13.223396 1.1561405,19.629883 23.07831,6.7491978 18.671333,9.2959874 14.344902,11.987543 9.8573789,14.389567 5.8103531,16.555807 17.78997,9.7680895 21.756041,7.4569649 c 0.21409,-0.1247553 -0.441297,0.229177 -0.642719,0.3734938 -0.63252,0.4531925 -1.255742,0.879984 -1.87055,1.3612245 -0.990862,1.2263148 -2.173114,2.3052708 -3.210427,3.4772508 0,0 -13.5862214,5.944429 -13.5862214,5.944429 z"
432 inkscape:connector-curvature="0" />
433 <path
434 style="fill:#000000;fill-opacity:1;stroke:none"
435 id="path3150"
436 d="m 44.537632,32.349942 c -5.147586,4.026032 -10.873455,6.771035 -16.655502,10.098737 -0.71409,0.686928 -1.63002,0.452279 -2.474519,0.671405 -0.401059,0.104064 -0.753081,0.349262 -1.144818,0.484244 0.736676,0.02838 -2.473393,1.416554 -1.731752,0.983942 29.062029,-16.9524 1.81009,-0.272962 -1.896399,1.014801 -1.286917,0.200555 -2.275566,1.042375 -3.532153,1.301287 -0.405308,0.554267 -1.065095,0.524248 -1.613699,0.795566 -0.662739,0.327763 -1.122742,0.692276 -1.857371,0.928714 -0.760106,0.785065 -1.819224,0.812321 -2.767366,1.163123 -0.474696,0.175632 -0.902223,0.461763 -1.370835,0.653036 -0.256593,0.07288 -0.525961,0.110449 -0.76978,0.218632 C 8.268551,50.865263 6.9846029,51.632281 7.4154555,51.383232 27.533295,39.754369 22.52409,42.532955 18.240391,45.295266 c -1.165488,0.819073 -2.012315,1.89418 -2.774998,3.081098 -0.845284,1.267918 -1.306169,2.696946 -1.894144,4.085429 -0.709336,1.412367 -0.787279,2.808431 -0.584867,4.335462 0.415146,1.308403 0.866784,2.618592 1.690615,3.729211 0.711541,1.116569 1.843939,1.954136 3.05544,2.471647 1.434799,0.587706 2.820424,1.107721 4.370221,1.331222 1.863012,0.201467 3.740237,0.197001 5.61174,0.204627 1.061154,-0.422861 2.259141,-0.406524 3.338121,-0.726337 0.500528,-0.148359 0.95492,-0.423492 1.442889,-0.609031 0.259577,-0.07197 0.531931,-0.107987 0.778732,-0.215924 0.228316,-0.09985 0.420765,-0.267119 0.631148,-0.400678 0.226794,-0.107396 0.447133,-0.229644 0.680383,-0.322187 0.768356,-0.304847 1.479129,-0.382367 2.210911,-0.783628 0.236171,-0.09699 0.929553,-0.418726 0.708513,-0.290959 -3.986257,2.304163 -8.00314,4.554946 -12.009817,6.823414 -0.211901,0.119973 0.413749,-0.25711 0.625248,-0.37779 4.424854,-2.524796 8.855737,-5.039013 13.283606,-7.55852 0,0 -11.493423,9.1721 -11.493423,9.1721 l 0,0 c 25.632954,-14.826031 4.799005,-2.558131 -2.652451,1.337169 -1.491162,0.456817 -2.849157,1.212206 -4.348056,1.647882 -1.608784,0.520829 -3.334322,0.82218 -5.021523,0.881289 -1.937875,-0.0244 -3.888043,-0.04197 -5.802052,-0.381372 C 8.46504,72.371171 6.9529525,71.749159 5.4402732,71.071006 4.1002399,70.2927 2.824761,69.338054 2,68 1.0937305,66.666625 0.5063194,65.186179 6.26e-5,63.660049 -0.2882245,61.935817 -0.448618,60.290055 0.2235018,58.61527 c 0.1864285,-0.460298 0.454071,-0.886178 0.6246649,-1.352577 0.3555415,-0.972041 0.4430375,-2.039925 1.2194084,-2.823626 0.4742277,-1.223862 1.4594908,-2.851226 2.5303973,-3.615873 0.5972416,-0.654754 0.3607951,-0.495492 1.1169283,-0.93613 5.5407473,-3.22888 9.7725723,-6.443379 15.3177753,-8.545059 1.391905,-0.595239 2.821693,-1.08014 4.148056,-1.823818 1.170505,-0.612883 2.349173,-1.244779 3.589444,-1.688564 1.099136,-0.541341 2.265558,-0.860322 3.384995,-1.366026 5.518505,-3.123477 -15.359314,8.690656 -11.325042,6.562985 4.683757,-2.470209 9.826663,-6.265044 15.072968,-8.467654 1.169288,-0.37991 2.379509,-0.540929 3.409749,-1.289413 -29.666352,17.271684 -10.82022,7.119963 -8.585469,4.48399 0,0 13.810255,-5.403563 13.810255,-5.403563 z"
437 inkscape:connector-curvature="0" />
438 </svg>""";
439 try {
440 File temp_file;
441 FileIOStream? ios;
442 DataOutputStream d;
443 FileOutputStream? os;
444
445 temp_file = get_child (BirdFont.get_settings_directory (), "inkscape_test.svg");
446
447 if (temp_file.query_exists ()) {
448 temp_file.delete ();
449 }
450
451 ios = temp_file.create_readwrite (FileCreateFlags.PRIVATE);
452 os = ((!) ios).output_stream as FileOutputStream?;
453 d = new DataOutputStream ((!) os);
454
455 d.put_string (inkscape_data);
456 d.close ();
457
458 test_open_next_glyph ();
459 SvgParser.import_svg ((!) temp_file.get_path ());
460
461 temp_file.delete ();
462 } catch (GLib.Error e) {
463 warning (e.message);
464 }
465 }
466
467 public static void test_spin_button () {
468 SpinButton s = new SpinButton ();
469 double last;
470 string e = "Wrong value in SpinButton";
471
472 s.set_max (1);
473 s.set_min (0);
474 s.set_value ("0.000");
475
476 if (s.get_display_value () != "0.000") {
477 warning (e);
478 }
479
480 s.increase ();
481
482 if (s.get_display_value () != "0.001") {
483 warning (e);
484 }
485
486 last = s.get_value ();
487 for (int i = 0; i < 100; i++) {
488 s.increase ();
489 if (last > s.get_value ()) {
490 warning (e);
491 }
492 last = s.get_value ();
493 }
494
495 if (s.get_display_value () != "0.101") {
496 warning (e);
497 }
498
499 s.set_value ("1.000");
500
501 if (s.get_display_value () != "1.000") {
502 warning (e);
503 }
504
505 last = s.get_value ();
506 for (int i = 0; i < 100; i++) {
507 s.decrease ();
508 if (last < s.get_value ()) {
509 warning (e);
510 }
511 last = s.get_value ();
512 }
513
514 if (s.get_display_value () != "0.900") {
515 warning (e);
516 }
517 }
518
519 public static void test_background_coordinates () {
520 BackgroundImage bg = new BackgroundImage ("");
521
522 bg.set_position (100, 100);
523 bg.set_img_offset (bg.img_offset_x, bg.img_offset_y);
524 warn_if_fail (bg.img_x == 100 && bg.img_y == 100);
525
526 bg.set_img_offset (100, 100);
527 bg.set_position (bg.img_x, bg.img_y);
528 warn_if_fail (bg.img_offset_x == 100 && bg.img_offset_y == 100);
529 }
530
531 public static void test_export () {
532 Glyph g;
533 Path p = new Path ();
534
535 test_open_next_glyph ();
536 g = MainWindow.get_current_glyph ();
537
538 p.add (-10, -10);
539 p.add (50, 50);
540 p.add (10, -10);
541
542 p.close ();
543 g.add_path (p);
544
545 MenuTab.preview ();
546
547 // TODO: run this many times on big fonts
548 for (int i = 0; i < 10; i++) {
549 MenuTab.export_fonts_in_background ();
550 Tool.yield ();
551 }
552 }
553
554 public static void test_preview () {
555 Glyph g;
556 Path p = new Path ();
557
558 test_open_next_glyph ();
559 g = MainWindow.get_current_glyph ();
560
561 p.add (-10, 10);
562 p.add (10, 10);
563 p.add (10, -10);
564 p.add (-10, -10);
565 p.close ();
566 g.add_path (p);
567
568 MenuTab.preview ();
569
570 // TODO: run this many times on big font
571 for (int i = 0; i < 100; i++) {
572 MainWindow.get_tab_bar ().select_tab_name ("Files");
573 Tool.yield ();
574
575 MainWindow.get_tab_bar ().select_tab_name ("Preview");
576 Tool.yield ();
577 }
578
579 }
580
581 public static void test_over_path () {
582 Glyph g;
583 Path p = new Path ();
584 Tool pen_tool;
585
586 pen_tool = MainWindow.get_toolbox ().get_tool ("pen_tool");
587 test_select_action (pen_tool);
588 test_open_next_glyph ();
589
590 g = MainWindow.get_current_glyph ();
591
592 test_click_action (pen_tool, 3, 10, 10);
593 test_click_action (pen_tool, 3, 10, 10);
594 test_click_action (pen_tool, 3, 100, 10);
595 test_click_action (pen_tool, 3, 100, 100);
596 test_click_action (pen_tool, 3, 10, 100);
597 test_click_action (pen_tool, 2, 0, 0);
598
599 g.close_path ();
600
601 warn_if_fail (g.active_paths.size == 0);
602
603 g.select_path (50, 50);
604
605 warn_if_fail (g.active_paths.size == 1);
606
607 p.add (-10, 10);
608 p.add (10, 10);
609 p.add (10, -10);
610 p.add (-10, -10);
611 p.update_region_boundaries();
612 g.add_path (p);
613 g.close_path ();
614
615 if (!p.is_over_coordinate (0, 0)) {
616 warning ("Coordinate 0, 0 is not in path.");
617 }
618
619 if (!p.is_over_coordinate (-10, 10)) {
620 warning ("Corner corrdinate -10, 10 is not in path.");
621 }
622
623 warn_if_fail (!p.is_over_coordinate (-20, -20));
624
625 for (double x = -10; x <= 10; x += 0.1) {
626 for (double y = 10; y <= 10; y += 0.1) {
627 warn_if_fail (p.is_over_coordinate (x, y));
628 }
629 }
630
631 }
632
633 public static void test_convert_to_quadratic_bezier_path () {
634 Glyph g;
635 Path p, p1;
636 EditPoint e0, e1, e2, e3;
637 List<Path> paths = new List<Path> ();
638
639 // convert the current path
640 g = MainWindow.get_current_glyph ();
641
642 foreach (Path path in g.path_list) {
643 paths.append (path.get_quadratic_points ());
644 paths.append (path.copy ());
645 }
646
647 // create a new path and convert it
648 test_open_next_glyph ();
649
650 p = new Path ();
651 p1 = new Path ();
652
653 g = MainWindow.get_current_glyph ();
654
655 p.add (-10, 10);
656 p.add (10, 10);
657 p.add (10, -10);
658 p.add (-10, -10);
659 p.close ();
660 g.add_path (p);
661 g.add_path (p1.get_quadratic_points ());
662
663 e0 = new EditPoint (20, 40);
664 e1 = new EditPoint (40, 40);
665 e2 = new EditPoint (40, 20);
666 e3 = new EditPoint (20, 20);
667
668 p1.add_point (e0);
669 p1.add_point (e1);
670 p1.add_point (e2);
671 p1.add_point (e3);
672 p1.close ();
673
674 e0.set_tie_handle (true);
675 e1.set_tie_handle (true);
676 e2.set_tie_handle (true);
677 e3.set_tie_handle (true);
678
679 e0.process_tied_handle ();
680 e1.process_tied_handle ();
681 e2.process_tied_handle ();
682 e3.process_tied_handle ();
683
684 g.add_path (p1);
685 g.add_path (p1.get_quadratic_points ());
686
687 foreach (Path path in paths) {
688 g.add_path (path);
689 }
690 }
691
692 public static void test_overview () {
693 OverView o = MainWindow.get_overview ();
694
695 warn_if_fail (o.selected_char_is_visible ());
696
697 for (int i = 0; i < 10; i++) {
698 o.key_down ();
699 warn_if_fail (o.selected_char_is_visible ());
700 }
701
702 for (int i = 0; i < 15; i++) {
703 o.key_up ();
704 warn_if_fail (o.selected_char_is_visible ());
705 }
706
707 for (int i = 0; i < 6; i++) {
708 o.key_down ();
709 warn_if_fail (o.selected_char_is_visible ());
710 }
711
712 for (int i = 0; i < 3; i++) {
713 o.key_down ();
714 warn_if_fail (o.selected_char_is_visible ());
715 }
716
717 for (int i = 0; i < 2000; i++) {
718 o.scroll_adjustment (5);
719 }
720
721 for (int i = 0; i < 2000; i++) {
722 o.scroll_adjustment (-5);
723 }
724 }
725
726 public static void test_data_reader () {
727 FontData fd = new FontData ();
728 uint len;
729 int v;
730
731 try {
732 fd.add (7);
733 fd.add_ulong (0x5F0F3CF5);
734 fd.add_ulong (9);
735
736 warn_if_fail (fd.table_data[0] == 7);
737 warn_if_fail (fd.read () == 7);
738 warn_if_fail (fd.read_ulong () == 0x5F0F3CF5);
739 warn_if_fail (fd.read_ulong () == 9);
740
741 fd = new FontData ();
742 for (int16 i = 0; i < 2048; i++) {
743 fd.add_short (i);
744 }
745
746 fd.seek (2 * 80);
747 warn_if_fail (fd.read_short () == 80);
748
749 fd.seek (100);
750 fd.add_short (7);
751 fd.seek (100);
752 warn_if_fail (fd.read_short () == 7);
753
754 fd.seek_end ();
755 len = fd.length ();
756 fd.add (0);
757 warn_if_fail (len + 1 == fd.length ());
758
759 fd.seek_end ();
760 for (int i = -1131; i < 1131; i++) {
761 fd.add_charstring_value (i);
762 }
763
764 for (int i = -1131; i < 1131; i++) {
765 v = fd.read_charstring_value ();
766 if (v != i) {
767 warning (@"expecting $i got $v\n");
768 }
769 }
770
771 } catch (GLib.Error e) {
772 warning (e.message);
773 }
774 }
775
776
777 public static void test_argument () {
778 Argument arg = new Argument ("supplement -t \"Argument list\" --unknown -unknown --help -s");
779
780 return_if_fail (arg.has_argument ("--test"));
781 return_if_fail ((!) arg.get_argument ("--test") == "\"Argument list\"" );
782 return_if_fail (arg.has_argument ("--unknown"));
783 return_if_fail (arg.has_argument ("--help"));
784 return_if_fail (arg.has_argument ("--slow"));
785 return_if_fail (arg.validate () != 0);
786
787 arg = new Argument ("supplement --test \"Argument list\"");
788 return_if_fail ((!) arg.get_argument ("--test") == "\"Argument list\"" );
789 return_if_fail (!arg.has_argument ("--help"));
790 return_if_fail (!arg.has_argument ("--slow"));
791 return_if_fail (arg.validate () == 0);
792
793 }
794
795 public static void test_glyph_ranges () {
796 GlyphRange gr = new GlyphRange ();
797 GlyphRange gr_az = new GlyphRange ();
798
799 gr.add_range ('b', 'c');
800 gr.add_single ('d');
801 gr.add_range ('e', 'h');
802 gr.add_range ('k', 'm');
803 gr.add_range ('o', 'u');
804 gr.add_range ('a', 'd');
805 gr.add_range ('f', 'z');
806 gr.add_range ('b', 'd');
807
808 gr.print_all ();
809
810 return_if_fail (gr.length () == 'z' - 'a' + 1);
811 return_if_fail (gr.get_ranges ().size == 1);
812 return_if_fail (gr.get_ranges ().get (0).length () == 'z' - 'a' + 1);
813
814 for (unichar i = 'a'; i <= 'z'; i++) {
815 uint index = i - 'a';
816 string c = gr.get_char (index);
817 StringBuilder s = new StringBuilder ();
818 s.append_unichar (i);
819
820 if (c != s.str) {
821 warning (@"wrong glyph in glyph range got \"$c\" expected \"$(s.str)\" for index $(index).");
822 }
823 }
824
825 gr = new GlyphRange ();
826 gr.add_single ('a');
827 gr.add_range ('c', 'e');
828 gr.add_single ('◊');
829 return_if_fail (gr.get_char (0) == "a");
830 return_if_fail (gr.get_char (1) == "c");
831 return_if_fail (gr.get_char (2) == "d");
832 return_if_fail (gr.get_char (3) == "e");
833 return_if_fail (gr.get_char (4) == "◊");
834
835 // a-z
836 gr_az.add_range ('a', 'z');
837 if (!gr_az.has_character ("g")) {
838 warning ("Can not g in range a-z ");
839 }
840
841 if (gr_az.has_character ("å")) {
842 warning ("Range a-z has å");
843 }
844
845 // codepage test for Latin 2
846 try {
847 gr = new GlyphRange ();
848 gr.parse_ranges ("- Ç ü-ý é á-â ä Ů-ű ç Ł-ń ë Ő-ő í-î Ä É Ĺ-ĺ ó-ô ö-÷ Ľ-ľ Ö-× Ü-Ý ú Ź-ž Ę-ě «- » ░-▓ │ ┤ Á-Â ╣ ═-║ ╗ ╝ ┐ └ ┴ ┬ ├ ─ ┼ Ă-ć ╚ ╔ ╩ ╦ ╠ ╬ ¤ Č-đ Ë Ň-ň Í-Î ┘ ┌ █ ▄ Ş-ť ▀ Ó-Ô ß Ŕ-ŕ Ú ´ ˝ ˛ ˇ ˘-˙ §-¨ ¸ ° Ř-ś ■ ");
849 if (!gr.has_character ("Ă")) {
850 warning ("Latin 2 range does not have Ă");
851 }
852
853 if (!gr.has_unichar ('Ă')) {
854 warning ("Latin 2 range does not have Ă");
855 }
856
857 if (!gr.has_unichar ('ó')) {
858 warning ("Latin 2 range does not have ó");
859 }
860 } catch (MarkupError e) {
861 warning (e.message);
862 }
863 }
864
865 public static void test_hex () {
866 test_hex_conv ('H', "U+48", 72);
867 test_hex_conv ('1', "U+31", 49);
868 test_hex_conv ('å', "U+e5", 229);
869 test_hex_conv ('◊', "U+25ca", 9674);
870 }
871
872 private static void test_hex_conv (unichar h, string sr, int r) {
873 string s = Font.to_hex (h);
874 unichar t = Font.to_unichar (sr);
875
876 if (s != sr) warning (@"($s != \"$sr\")");
877 if ((int)t != r || t != h) warning (@"$((int)t) != $r || $t != '$h'");
878 }
879
880 // test pen tool
881 /** Draw a test glyph. */
882 public static void test_drawing () {
883 Tool pen_tool = MainWindow.get_toolbox ().get_tool ("pen_tool");
884
885 test_select_action (pen_tool);
886
887 test_open_next_glyph ();
888
889 // paint
890 test_click_action (pen_tool, 1, 30, 30);
891 test_click_action (pen_tool, 1, 60, 30);
892 test_click_action (pen_tool, 1, 60, 60);
893 test_click_action (pen_tool, 1, 30, 60);
894
895 // close
896 test_click_action (pen_tool, 3, 0, 0);
897
898 // reopen
899 test_click_action (pen_tool, 3, 35, 35);
900
901 // move around
902 test_move_action (pen_tool, 100, 200);
903 test_move_action (pen_tool, 20, 300);
904 test_move_action (pen_tool, 0, 0);
905
906 // add to path
907 test_move_action (pen_tool, 70, 50);
908
909 test_click_action (pen_tool, 1, 70, 50);
910 test_click_action (pen_tool, 1, 70, 50);
911 test_click_action (pen_tool, 1, 70, 100);
912 test_click_action (pen_tool, 1, 50, 100);
913 test_click_action (pen_tool, 1, 50, 50);
914
915 // close
916 test_click_action (pen_tool, 3, 0, 0);
917 Tool.yield ();
918 }
919
920 /** Test path coordinates and reverse path coordinates. */
921 public static void test_coordinates () {
922 int x, y, xc, yc;
923 double px, py, mx, my;
924 string n;
925 Tool pen_tool = MainWindow.get_toolbox ().get_tool ("pen_tool");
926
927 test_open_next_glyph ();
928 Glyph g = MainWindow.get_current_glyph ();
929
930 xc = (int) (g.allocation.width / 2.0);
931 yc = (int) (g.allocation.height / 2.0);
932
933 g.default_zoom ();
934
935 x = 10;
936 y = 15;
937
938 px = Glyph.path_coordinate_x (x);
939 py = Glyph.path_coordinate_y (y);
940
941 mx = x * Glyph.ivz () - Glyph.xc () + g.view_offset_x;
942 my = Glyph.yc () - y * Glyph.ivz () - g.view_offset_y;
943
944 if (mx != px || my != py) {
945 warning (@"bad coordinate $mx != $px || $my != $py");
946 }
947
948 test_reverse_coordinate (x, y, px, py, "ten fifteen");
949 test_click_action (pen_tool, 1, x, y);
950
951 // offset no zoom
952 n = "Offset no zoom";
953 g.reset_zoom ();
954
955 px = Glyph.path_coordinate_x (x);
956 py = Glyph.path_coordinate_y (y);
957
958 test_reverse_coordinate (x, y, px, py, n);
959 test_click_action (pen_tool, 1, x, y);
960
961 // close path
962 test_click_action (pen_tool, 3, x, y);
963 }
964
965 private static void test_reverse_coordinate (int x, int y, double px, double py, string n) {
966 if (x != Glyph.reverse_path_coordinate_x (px) || Glyph.reverse_path_coordinate_y (py) != y) {
967 warning (@"Reverse coordinates does not match current point for test case \"$n\".\n $x != $(Glyph.reverse_path_coordinate_x (px)) || $(Glyph.reverse_path_coordinate_y (py)) != $y (x != Glyph.reverse_path_coordinate_x (px) || Glyph.reverse_path_coordinate_y (py) != y)");
968 }
969 }
970
971 private static void test_last_is_clockwise (string name) {
972 bool d = ((!)MainWindow.get_current_glyph ().get_last_path ()).is_clockwise ();
973
974 if (!d) {
975 critical (@"\nPath $name is counter clockwise, in test_last_is_clockwise");
976 }
977
978 }
979
980 private static bool test_reverse_last (string name)
981 requires (MainWindow.get_current_glyph ().get_last_path () != null)
982 {
983 Glyph g = MainWindow.get_current_glyph ();
984 Path p = (!) g.get_last_path ();
985 bool direction = p.is_clockwise ();
986
987 p.reverse ();
988
989 if (direction == p.is_clockwise ()) {
990 critical (@"Direction did not change after reverseing path \"$name\"\n");
991 stderr.printf (@"Path length: $(p.points.size) \n");
992 return false;
993 }
994
995 Tool.yield ();
996 return true;
997 }
998
999 class Point {
1000
1001 public int x;
1002 public int y;
1003
1004 public Point (int x, int y) {
1005 this.x = x;
1006 this.y = y;
1007 }
1008 }
1009
1010 private static Point p (int x, int y) {
1011 return new Point (x, y);
1012 }
1013
1014 private static void test_triangle (Point a, Point b, Point c, string name = "") {
1015 Tool pen_tool = MainWindow.get_toolbox ().get_tool ("pen_tool");
1016
1017 Tool.yield ();
1018 MainWindow.get_tab_bar ().select_overview ();
1019
1020 Tool.yield ();
1021 MainWindow.get_overview ().open_current_glyph ();
1022
1023 test_select_action (pen_tool);
1024
1025 test_click_action (pen_tool, 3, a.x, a.y);
1026 test_click_action (pen_tool, 3, b.x, b.y);
1027 test_click_action (pen_tool, 3, c.x, c.y);
1028
1029 test_reverse_last (@"Triangle reverse \"$name\" ($(a.x), $(a.y)), ($(b.x), $(b.y)), ($(c.x), $(c.y)) failed.");
1030
1031 Tool.yield ();
1032 }
1033
1034 private static void test_various_triangles () {
1035 test_triangle (p (287, 261), p (155, 81), p (200, 104), "First");
1036 test_triangle (p (65, 100), p (168, 100), p (196, 177), "Second");
1037 test_triangle (p (132, 68), p (195, 283), p (195, 222), "Third");
1038 test_triangle (p (144, 267), p (147, 27), p (296, 267), "Fourth");
1039 }
1040
1041 public static void test_reverse_path () {
1042 // open a new glyph
1043 Tool pen_tool = MainWindow.get_toolbox ().get_tool ("pen_tool");
1044
1045 Tool.yield ();
1046 MainWindow.get_tab_bar ().select_overview ();
1047
1048 Tool.yield ();
1049 MainWindow.get_overview ().open_current_glyph ();
1050
1051 test_select_action (pen_tool);
1052
1053 // paint
1054 int x_offset = 10;
1055 int y_offset = 10;
1056
1057 test_open_next_glyph ();
1058 test_various_triangles ();
1059
1060 test_open_next_glyph ();
1061 // draw clockwise and check direction
1062
1063 y_offset += 160;
1064 test_click_action (pen_tool, 3, 10 + x_offset, 20 + y_offset);
1065 test_click_action (pen_tool, 3, 17 + x_offset, 17 + y_offset);
1066 test_click_action (pen_tool, 3, 20 + x_offset, 0 + y_offset);
1067 test_click_action (pen_tool, 2, 0, 0);
1068 test_last_is_clockwise ("Clockwise triangle 1.2");
1069
1070 // draw paths clockwise / counter clockwise and reverse them
1071
1072 test_click_action (pen_tool, 3, 115, 137);
1073 test_click_action (pen_tool, 3, 89, 74);
1074 test_click_action (pen_tool, 3, 188, 232);
1075 test_click_action (pen_tool, 2, 0, 0);
1076 test_reverse_last ("Triangle 0");
1077
1078 // draw incomplete paths
1079 y_offset += 20;
1080 test_click_action (pen_tool, 3, 10 + x_offset, 20 + y_offset);
1081 test_reverse_last ("Point");
1082 test_click_action (pen_tool, 2, 0, 0);
1083
1084 y_offset += 20;
1085 test_click_action (pen_tool, 3, 10 + x_offset, 20 + y_offset);
1086 test_click_action (pen_tool, 3, 10 + x_offset, 20 + y_offset);
1087 test_reverse_last ("Double point");
1088 test_click_action (pen_tool, 2, 0, 0);
1089
1090 y_offset += 20;
1091 test_click_action (pen_tool, 3, 10 + x_offset, 30 + y_offset);
1092 test_click_action (pen_tool, 3, 10 + x_offset, 20 + y_offset);
1093 test_reverse_last ("Vertical line");
1094 test_click_action (pen_tool, 2, 0, 0);
1095
1096 y_offset += 20;
1097 test_click_action (pen_tool, 1, 30 + x_offset, 20 + y_offset);
1098 test_click_action (pen_tool, 1, 10 + x_offset, 20 + y_offset);
1099 test_click_action (pen_tool, 3, 0, 0);
1100 test_reverse_last ("Horisontal line");
1101 test_click_action (pen_tool, 2, 0, 0);
1102
1103 // triangle 1
1104 y_offset += 20;
1105 test_click_action (pen_tool, 3, 10 + x_offset, -10 + y_offset);
1106 test_click_action (pen_tool, 3, 20 + x_offset, 20 + y_offset);
1107 test_click_action (pen_tool, 3, 30 + x_offset, 0 + y_offset);
1108 test_reverse_last ("Triangle reverse 1");
1109 test_click_action (pen_tool, 2, 0, 0);
1110
1111 // box
1112 y_offset += 20;
1113 test_click_action (pen_tool, 3, 100 + x_offset, 150 + y_offset);
1114 test_click_action (pen_tool, 3, 150 + x_offset, 150 + y_offset);
1115 test_click_action (pen_tool, 3, 150 + x_offset, 100 + y_offset);
1116 test_click_action (pen_tool, 3, 100 + x_offset, 100 + y_offset);
1117 test_reverse_last ("Box 1");
1118 test_click_action (pen_tool, 2, 0, 0);
1119 }
1120
1121 private static Tool select_pen () {
1122 Tool pen_tool = MainWindow.get_toolbox ().get_tool ("pen_tool");
1123 test_select_action (pen_tool);
1124 return pen_tool;
1125 }
1126
1127 public static void test_delete_points () {
1128 PenTool pen;
1129
1130 test_open_next_glyph ();
1131
1132 pen = (PenTool) select_pen ();
1133
1134 // draw a line with ten points
1135 for (int i = 1; i <= 10; i++) {
1136 test_click_action (pen, 3, 20*i, 20);
1137 }
1138
1139 // TODO: it would be nice to test if points were created here
1140
1141 // delete points
1142 for (int i = 1; i <= 10; i++) {
1143 test_move_action (pen, 20 * i, 20);
1144 test_click_action (pen, 1, 20*i, 20);
1145 PenTool.delete_selected_points ();
1146 }
1147 }
1148
1149 public static void test_reverse_random_triangles () {
1150 Tool pen;
1151
1152 int ax, bx, cx;
1153 int ay, by, cy;
1154
1155 bool r = true;
1156
1157 test_open_next_glyph ();
1158 pen = select_pen ();
1159
1160 for (int i = 0; i < 30; i++) {
1161 Tool.yield ();
1162
1163 ax = Random.int_range (0, 300);
1164 bx = Random.int_range (0, 300);
1165 cx = Random.int_range (0, 300);
1166
1167 ay = Random.int_range (0, 300);
1168 by = Random.int_range (0, 300);
1169 cy = Random.int_range (0, 300);
1170
1171 test_click_action (pen, 3, ax, ay);
1172 test_click_action (pen, 3, bx, by);
1173 test_click_action (pen, 3, cx, cy);
1174 test_click_action (pen, 2, 0, 0);
1175
1176 r = test_reverse_last (@"Random triangle № $(i + 1) ($ax, $ay), ($bx, $by), ($cx, $cy)");
1177 if (!r) {
1178 test_open_next_glyph ();
1179 pen = select_pen ();
1180
1181 test_click_action (pen, 3, ax, ay);
1182 test_click_action (pen, 3, bx, by);
1183 test_click_action (pen, 3, cx, cy);
1184 test_click_action (pen, 2, 0, 0);
1185
1186 return;
1187 }
1188
1189 test_open_next_glyph ();
1190 }
1191
1192 if (r) test_open_next_glyph ();
1193 }
1194
1195
1196 /** Help function to test button press actions. */
1197 public static void test_click_action (Tool t, int b, int x, int y) {
1198 Tool.yield ();
1199 t.press_action (t, b, x, y);
1200
1201 Tool.yield ();
1202 t.release_action (t, b, x, y);
1203 }
1204
1205 /** Help function to test select action for this tool. */
1206 public static void test_select_action (Tool t) {
1207 Toolbox tb = MainWindow.get_toolbox ();
1208 Tool.yield ();
1209 tb.select_tool (t);
1210 }
1211
1212 public static void test_move_action (Tool t, int x, int y) {
1213 Tool.yield ();
1214 t.move_action (t, x, y);
1215 }
1216
1217 public static void test_open_next_glyph () {
1218 OverView o = MainWindow.get_overview ();
1219
1220 MainWindow.get_tab_bar ().select_overview ();
1221 Toolbox.select_tool_by_name ("utf_8");
1222 Tool.yield ();
1223
1224 o.select_next_glyph ();
1225 Tool.yield ();
1226
1227 o.open_current_glyph ();
1228 Tool.yield ();
1229 }
1230
1231 private static void test_boundaries () {
1232 Preferences.draw_boundaries = true;
1233 }
1234
1235 private static void test_raster_path () {
1236 Glyph g = MainWindow.get_current_glyph ();
1237 PathList pl = new PathList ();
1238 Path path;
1239
1240 test_open_next_glyph ();
1241 test_inkscape_import (); // draw somee thing
1242
1243 foreach (Path p in g.path_list) {
1244 path = new Path ();
1245 p.all_of_path ((cx, cy, ct) => {
1246 path.add (cx, cy);
1247 return true;
1248 });
1249 pl.add (path);
1250 }
1251
1252 test_open_next_glyph ();
1253
1254 foreach (Path p in pl.paths) {
1255 g.add_path (p);
1256 }
1257 }
1258
1259 private static void test_file_path () {
1260 Font f = new Font ();
1261 File file;
1262 string folder;
1263
1264 f.font_file = "E:\\Typeface.bf";
1265 folder = f.get_folder_path ();
1266 if (folder != "E:") {
1267 warning (@"Wrong folder, $folder");
1268 }
1269
1270 f.font_file = "/home/user/Typeface.bf";
1271 folder = f.get_folder_path ();
1272 if (folder != "/home/user") {
1273 warning (@"Wrong folder, $folder");
1274 }
1275
1276 f.font_file = "./Typeface.bf";
1277 file = File.new_for_path (".");
1278 folder = f.get_folder_path ();
1279 if (((!)file.get_path ()) != folder) {
1280 warning (@"Wrong folder, $folder");
1281 }
1282
1283 f.font_file = "./Typeface.bf";
1284 folder = f.get_folder_path ();
1285 if (!folder.has_prefix ("/")) {
1286 warning (@"Wrong folder, $folder");
1287 }
1288 }
1289
1290 static void test_xml () {
1291 Tag root;
1292 XmlParser parser;
1293
1294 parser = new XmlParser ("""<g><g><g></g><g><g></g></g></g></g>""");
1295
1296 root = parser.get_root_tag ();
1297 print_tags (root);
1298
1299 if (parser.validate ()) {
1300 root = parser.get_root_tag ();
1301 print_tags (root);
1302 } else {
1303 warning ("Invalid XML code.");
1304 }
1305
1306 }
1307
1308 static void print_tags (Tag tag) {
1309 print (tag.get_name ());
1310 print ("\n");
1311 print_attributes (tag);
1312 print (tag.get_content ());
1313
1314 foreach (Tag t in tag) {
1315 print_tags (t);
1316 }
1317 }
1318
1319 static void print_attributes (Tag tag) {
1320 Attributes attributes = tag.get_attributes ();
1321 foreach (Attribute attribute in attributes) {
1322 print ("\t");
1323 print (attribute.get_name ());
1324 print ("\n");
1325 }
1326 }
1327
1328 }
1329
1330 }
1331