]> git.donarmstrong.com Git - lilypond.git/blob - mf/feta-noteheads.mf
Merge branch 'master' into lilypond/translation
[lilypond.git] / mf / feta-noteheads.mf
1 % Feta (not the Font-En-Tja) music font -- implement noteheads
2 % This file is part of LilyPond, the GNU music typesetter.
3 %
4 % Copyright (C) 1997--2011 Jan Nieuwenhuizen <janneke@gnu.org>
5 % & Han-Wen Nienhuys <hanwen@xs4all.nl>
6 % & Juergen Reuter <reuter@ipd.uka.de>
7 %
8 %
9 % LilyPond is free software: you can redistribute it and/or modify
10 % it under the terms of the GNU General Public License as published by
11 % the Free Software Foundation, either version 3 of the License, or
12 % (at your option) any later version.
13 %
14 % LilyPond is distributed in the hope that it will be useful,
15 % but WITHOUT ANY WARRANTY; without even the implied warranty of
16 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 % GNU General Public License for more details.
18 %
19 % You should have received a copy of the GNU General Public License
20 % along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
21
22 test_outlines := 0;
23
24
25 save remember_pic;
26 picture remember_pic;
27
28
29 % Most beautiful noteheads are pronounced, not circular,
30 % and not even symmetric.
31 % These examples are inspired by [Wanske]; see literature list.
32
33
34
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 % NOTE HEAD VARIABLES
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38
39 save half_notehead_width, whole_notehead_width;
40 save solfa_noteheight;
41
42 numeric whole_notehead_width;
43 numeric half_notehead_width;
44
45 fet_begingroup ("noteheads");
46
47
48 %
49 % solfa heads should not overlap on chords.
50 %
51 solfa_noteheight# := staff_space# - stafflinethickness#;
52
53 def undraw_inside_ellipse (expr ellipticity, tilt, superness, clearance) =
54 begingroup
55         save pat;
56         path pat;
57
58         pat := superellipse ((ellipticity, 0), (0, 1.0),
59                              (-ellipticity, 0), (0, -1.0),
60                              superness);
61         pat := pat rotated tilt;
62
63         save top_point, right_point;
64         pair top_point, right_point;
65
66         top_point := directionpoint left of pat;
67         right_point := directionpoint up of pat;
68
69         save height, scaling;
70
71         height# = staff_space# + stafflinethickness# - clearance;
72         scaling# = height# / (2 ypart (top_point));
73         define_pixels (scaling);
74         pat := pat scaled scaling shifted (w / 2, .5 (h - d));
75
76         if test_outlines = 1:
77                 draw pat;
78         else:
79                 unfill pat;
80         fi
81 endgroup;
82 enddef;
83
84
85 %
86 % dimensions aren't entirely right.
87 %
88 def draw_longa (expr up) =
89         save stemthick, fudge;
90
91         stemthick# = 2 stafflinethickness#;
92         define_whole_blacker_pixels (stemthick);
93
94         fudge = hround (blot_diameter / 2);
95
96         draw_outside_ellipse (1.80, 0, 0.707, 0);
97         undraw_inside_ellipse (1.30, 125, 0.68, 2 stafflinethickness#);
98
99         pickup pencircle scaled stemthick;
100
101         if up:
102                 bot y1 = -d;
103                 top y2 = h;
104                 rt x1 - fudge = 0;
105                 x1 = x2;
106
107                 fudge + lft x3 = w;
108                 x4 = x3;
109                 top y4 = h + 3.0 staff_space;
110                 y3 = y1;
111         else:
112                 bot y1 = -d - 3.0 staff_space;
113                 top y2 = h;
114                 rt x1 - fudge = 0;
115                 x1 = x2;
116
117                 fudge + lft x3 = w;
118                 x4 = x3;
119                 y4 = y2;
120                 bot y3 = -d;
121         fi;
122
123         draw_gridline (z1, z2, stemthick);
124         draw_gridline (z3, z4, stemthick);
125
126         labels (1, 2, 3, 4);
127 enddef;
128
129
130 fet_beginchar ("Longa notehead", "uM2");
131         draw_longa (true);
132
133         draw_staff (-2, 2, 0);
134 fet_endchar;
135
136
137 fet_beginchar ("Longa notehead", "dM2");
138         draw_longa (false);
139
140         draw_staff (-2, 2, 0);
141 fet_endchar;
142
143
144 if test > 0:
145         fet_beginchar ("Longa notehead", "uM2");
146                 draw_longa (true);
147
148                 draw_staff (-2, 2, 0.5);
149         fet_endchar;
150
151
152         fet_beginchar ("Longa notehead", "dM2");
153                 draw_longa (false);
154
155                 draw_staff (-2, 2, 0.5);
156         fet_endchar;
157 fi;
158
159
160 %
161 % dimensions aren't entirely right.
162 %
163 def draw_brevis (expr linecount) =
164         save stemthick, fudge;
165
166         stemthick# = 2 stafflinethickness#;
167         define_whole_blacker_pixels (stemthick);
168
169         fudge = hround (blot_diameter / 2);
170
171         draw_outside_ellipse (1.80, 0, 0.707, 0);
172         undraw_inside_ellipse (1.30, 125, 0.68, 2 stafflinethickness#);
173
174         pickup pencircle scaled stemthick;
175
176         bot y1 = -d;
177         top y2 = h;
178         rt x1 - fudge = 0;
179         x1 = x2;
180
181         fudge + lft x3 = w;
182         x4 = x3;
183         y4 = y2;
184         y3 = y1;
185
186         for i := 0 step 1 until linecount - 1:
187                 draw_gridline (z1 - (1.5 * i * stemthick, 0),
188                                z2 - (1.5 * i * stemthick, 0), stemthick);
189                 draw_gridline (z3 + (1.5 * i * stemthick, 0),
190                                z4 + (1.5 * i * stemthick, 0), stemthick);
191         endfor;
192 enddef;
193
194
195 fet_beginchar ("Brevis notehead", "sM1");
196         draw_brevis (1);
197
198         draw_staff (-2, 2, 0);
199 fet_endchar;
200
201
202 if test > 0:
203         fet_beginchar ("Brevis notehead", "sM1");
204                 draw_brevis(1);
205
206                 draw_staff (-2, 2, 0.5);
207         fet_endchar;
208 fi;
209
210
211 fet_beginchar ("Double-lined brevis notehead", "sM1double");
212         draw_brevis (2);
213
214         draw_staff (-2, 2, 0);
215 fet_endchar;
216
217
218 if test > 0:
219         fet_beginchar ("Double-lined brevis notehead", "sM1double");
220                 draw_brevis (2);
221
222                 draw_staff (-2, 2, 0.5);
223         fet_endchar;
224 fi;
225
226
227 fet_beginchar ("Whole notehead", "s0");
228         draw_outside_ellipse (1.80 - puff_up_factor / 3.0, 0, 0.707, 0);
229         undraw_inside_ellipse (1.30, 125 - puff_up_factor * 10,
230                                0.68, 2 stafflinethickness#);
231
232         whole_notehead_width# := charwd;
233
234         draw_staff (-2, 2, 0);
235 fet_endchar;
236
237
238 if test > 0:
239         fet_beginchar ("Whole notehead", "s0");
240                 draw_outside_ellipse (1.80 - puff_up_factor / 3.0, 0,
241                                       0.707, 0);
242                 undraw_inside_ellipse (1.30, 125 - puff_up_factor * 10,
243                                        0.68, 2 stafflinethickness#);
244
245                 draw_staff (-2, 2, 0.5);
246         fet_endchar;
247 fi;
248
249
250 fet_beginchar ("Half notehead", "s1");
251         draw_outside_ellipse (1.53 - puff_up_factor / 3.0, 34, 0.66, 0.17);
252         undraw_inside_ellipse (3.25, 33, 0.81, 2.5 stafflinethickness#);
253
254         half_notehead_width# := charwd;
255
256         draw_staff (-2, 2, 0);
257 fet_endchar;
258
259
260 if test > 0:
261         fet_beginchar ("Half notehead", "s1");
262                 draw_outside_ellipse (1.53 - puff_up_factor / 3.0, 34,
263                                       0.66, 0.17);
264                 undraw_inside_ellipse (3.25, 33, 0.81,
265                                        2.5 stafflinethickness#);
266
267                 draw_staff (-2, 2, 0.5);
268         fet_endchar;
269 fi;
270
271
272 fet_beginchar ("Quarter notehead", "s2");
273         draw_quarter_path;
274         draw_staff (-2, 2, 0);
275 fet_endchar;
276
277
278 if test > 0:
279         fet_beginchar ("Quarter notehead", "s2");
280                 draw_outside_ellipse (1.49 - puff_up_factor / 3.0, 31,
281                                       0.707, 0);
282
283                 draw_staff (-2, 2, 0.5);
284         fet_endchar;
285 fi;
286
287
288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
289
290
291 fet_beginchar ("Whole diamondhead", "s0diamond");
292         draw_outside_ellipse (1.80, 0, 0.495, 0);
293         undraw_inside_ellipse (1.30, 125, 0.6,
294                                .4 staff_space# + stafflinethickness#);
295
296         draw_staff (-2, 2, 0);
297 fet_endchar;
298
299
300 if test > 0:
301         fet_beginchar ("Whole diamondhead", "s0diamond");
302                 draw_outside_ellipse (1.80, 0, 0.495, 0);
303                 undraw_inside_ellipse (1.30, 125, 0.6,
304                                        .4 staff_space# + stafflinethickness#);
305
306                 draw_staff (-2, 2, 0.5);
307         fet_endchar;
308 fi;
309
310
311 fet_beginchar ("Half diamondhead", "s1diamond");
312         draw_outside_ellipse (1.50, 34, 0.49, 0.17);
313         undraw_inside_ellipse (3.5, 33, 0.80,
314                                .3 staff_space# + 1.5 stafflinethickness#);
315
316         draw_staff (-2, 2, 0);
317 fet_endchar;
318
319
320 if test > 0:
321         fet_beginchar ("Half diamondhead", "s1diamond");
322                 draw_outside_ellipse (1.50, 34, 0.49, 0.17);
323                 undraw_inside_ellipse (3.5, 33, 0.80,
324                                        .3 staff_space#
325                                        + 1.5 stafflinethickness#);
326
327                 draw_staff (-2, 2, 0.5);
328         fet_endchar;
329 fi;
330
331
332 fet_beginchar ("Quarter diamondhead", "s2diamond");
333         draw_outside_ellipse (1.80, 35, 0.495, -0.25);
334
335         draw_staff (-2, 2, 0);
336 fet_endchar;
337
338
339 if test > 0:
340         fet_beginchar ("Quarter diamondhead", "s2diamond");
341                 draw_outside_ellipse (1.80, 35, 0.495, -0.25);
342
343                 draw_staff (-2, 2, 0.5);
344         fet_endchar;
345 fi;
346
347
348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
349
350
351 vardef penposx@# (expr d) =
352 begingroup;
353         save pat;
354         path pat;
355
356         pat = top z@#
357               .. lft z@#
358               .. bot z@#
359               .. rt z@#
360               .. cycle;
361         z@#l = pat intersectionpoint (z@# -- infinity * dir (d + 180));
362         z@#r = pat intersectionpoint (z@# -- infinity * dir (d));
363 endgroup
364 enddef;
365
366
367 %
368 % UGH: xs not declared as argument.
369 %
370 def define_triangle_shape (expr stemdir) =
371         save triangle_a, triangle_b, triangle_c;
372         save triangle_out_a, triangle_out_b, triangle_out_c;
373         save triangle_in, triangle_out;
374         save width, depth, height;
375         save origin, left_up_dir;
376         save exact_left_point, exact_right_point, exact_down_point;
377
378         path triangle_a, triangle_b, triangle_c;
379         path triangle_out_a, triangle_out_b, triangle_out_c;
380         path triangle_in, triangle_out;
381         pair origin, left_up_dir;
382         pair exact_down_point, exact_left_point, exact_right_point;
383
384         save pen_thick;
385         pen_thick# = stafflinethickness# + .1 staff_space#;
386         define_pixels (llap);
387         define_blacker_pixels (pen_thick);
388
389         left_up_dir = llap# * dir (90 + tilt);
390
391         xpart (left_up_dir) * xs - (pen_thick# * xs) / 2 + xpart origin = 0;
392         ypart origin = 0;
393
394         exact_left_point := origin + (left_up_dir xscaled xs);
395         exact_down_point := origin + (left_up_dir rotated 120 xscaled xs);
396         exact_right_point := origin + (left_up_dir rotated 240 xscaled xs);
397
398         height# = ypart (exact_left_point + origin) + pen_thick# / 2;
399         depth# = -ypart (exact_down_point + origin) + pen_thick# / 2;
400         width# = xpart (exact_right_point - exact_left_point)
401                  + pen_thick# * xs;
402
403         set_char_box (0, width#, depth#, height#);
404
405         % Formerly, the shape has simply been drawn with an elliptical pen
406         % (`scaled pen_thick xscaled xs'), but the envelope of such a curve
407         % is of 6th degree.  For the sake of mf2pt1, we approximate it.
408
409         pickup pencircle scaled pen_thick xscaled xs;
410
411         z0 = (hround_pixels (xpart origin), 0);
412
413         z1 = z1' = z0 + llap * dir (90 + tilt) xscaled xs;
414         z2 = z2' = z0 + llap * dir (90 + tilt + 120) xscaled xs;
415         z3 = z3' = z0 + llap * dir (90 + tilt + 240) xscaled xs;
416
417         z12 = caveness [.5[z1, z2], z3];
418         z23 = caveness [.5[z2, z3], z1];
419         z31 = caveness [.5[z3, z1], z2];
420
421         triangle_a = z1 .. z12 .. z2;
422         triangle_b = z2 .. z23 .. z3;
423         triangle_c = z3 .. z31 .. z1;
424
425         penposx1 (angle (direction 0 of triangle_a) - 90);
426         penposx2 (angle (direction 0 of triangle_b) - 90);
427         penposx3 (angle (direction 0 of triangle_c) - 90);
428
429         penposx1' (angle (direction infinity of triangle_c) + 90);
430         penposx2' (angle (direction infinity of triangle_a) + 90);
431         penposx3' (angle (direction infinity of triangle_b) + 90);
432
433         penposx12 (angle (z12 - z0));
434         penposx23 (angle (z23 - z0));
435         penposx31 (angle (z31 - z0));
436
437         z10 = (z0 -- z1) intersectionpoint (z1l .. z12l .. z2'r);
438         z20 = (z0 -- z2) intersectionpoint (z2l .. z23l .. z3'r);
439         z30 = (z0 -- z3) intersectionpoint (z3l .. z31l .. z1'r);
440
441         triangle_in = z10
442                       .. z12l
443                       .. z20
444                       & z20
445                       .. z23l
446                       .. z30
447                       & z30
448                       .. z31l
449                       .. z10
450                       & cycle;
451
452         triangle_out_a = z1r .. z12r .. z2'l;
453         triangle_out_b = z2r .. z23r .. z3'l;
454         triangle_out_c = z3r .. z31r .. z1'l;
455
456         triangle_out = top z1
457                        .. lft z1
458                        .. z1r{direction 0 of triangle_out_a}
459                        & triangle_out_a
460                        & {direction infinity of triangle_out_a}z2'l
461                        .. lft z2
462                        .. bot z2
463                        .. z2r{direction 0 of triangle_out_b}
464                        & triangle_out_b
465                        & {direction infinity of triangle_out_b}z3'l
466                        .. rt z3
467                        .. top z3
468                        .. z3r{direction 0 of triangle_out_c}
469                        & triangle_out_c
470                        & {direction infinity of triangle_out_c}z1'l
471                        .. cycle;
472
473         labels (0, 10, 20, 30);
474         penlabels (1, 1', 2, 2', 3, 3', 12, 23, 31);
475
476         % attachment Y
477         if stemdir = 1:
478                 charwy := ypart exact_right_point;
479                 charwx := xpart exact_right_point + .5 pen_thick# * xs;
480         else:
481                 charwy := -ypart exact_down_point;
482                 charwx := width# - (xpart exact_down_point - .5 pen_thick# * xs);
483         fi
484 enddef;
485
486
487 def draw_whole_triangle_head =
488         save hei, xs;
489         save llap;
490         save tilt;
491
492         tilt = 40;
493         llap# = 3/4 noteheight#;
494
495         xs = 1.5;
496         caveness := 0.1;
497         define_triangle_shape (1);
498         fill triangle_out;
499         unfill triangle_in;
500 enddef;
501
502
503 fet_beginchar ("Whole trianglehead", "s0triangle");
504         draw_whole_triangle_head;
505
506         draw_staff (-2, 2, 0);
507 fet_endchar;
508
509
510 if test > 0:
511         fet_beginchar ("Whole trianglehead", "s0triangle");
512                 draw_whole_triangle_head;
513
514                 draw_staff (-2, 2, 0.5);
515         fet_endchar;
516 fi;
517
518
519 def draw_small_triangle_head (expr dir) =
520         save hei, xs;
521         save llap;
522         save tilt;
523
524         tilt = 40;
525         llap# = 2/3 noteheight#;
526         xs = 1.2;
527         caveness := 0.1;
528         define_triangle_shape (dir);
529
530         pickup feta_fillpen;
531
532         filldraw triangle_out;
533         unfilldraw triangle_in;
534 enddef;
535
536
537 fet_beginchar ("Half trianglehead (downstem)", "d1triangle");
538         draw_small_triangle_head (-1);
539
540         draw_staff (-2, 2, 0);
541 fet_endchar;
542
543
544 fet_beginchar ("Half trianglehead (upstem)", "u1triangle");
545         draw_small_triangle_head (1);
546
547         draw_staff (-2, 2, 0.5);
548 fet_endchar;
549
550
551 def draw_closed_triangle_head (expr dir) =
552         save hei, xs;
553         save llap;
554         save tilt;
555
556         tilt = 40;
557         llap# = 2/3 noteheight#;
558         xs = 1.0;
559         caveness := 0.1;
560         define_triangle_shape (dir);
561         fill triangle_out;
562 enddef;
563
564
565 fet_beginchar ("Quarter trianglehead (upstem)", "u2triangle");
566         draw_closed_triangle_head (1);
567
568         draw_staff (-2, 2, 0);
569 fet_endchar;
570
571
572 fet_beginchar ("Quarter trianglehead (downstem)", "d2triangle");
573         draw_closed_triangle_head (-1);
574
575         draw_staff (-2, 2, 0.5);
576 fet_endchar;
577
578
579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
580 %
581 % Slash heads are for indicating improvisation.  They are
582 % twice as high as normal heads.
583 %
584 def draw_slash (expr hwid_hash) =
585         save exact_height;
586         save ne, nw_dist;
587         pair ne, nw_dist;
588         exact_height = staff_space# + stafflinethickness# / 2;
589
590         set_char_box (0, 2 exact_height / slash_slope + hwid_hash,
591                       exact_height, exact_height);
592
593         charwx := charwd;
594         charwy := charht;
595
596         clearxy;
597
598         d := d - feta_shift;
599
600         pickup pencircle scaled blot_diameter;
601
602         bot y1 = -d;
603         top y2 = h;
604         lft x1 = 0;
605         lft x2 = 2 h / slash_slope;
606
607         rt x3 = w;
608         y3 = y2;
609         y4 = y1;
610         x3 - x2 = x4 - x1;
611
612         ne = unitvector (z3 - z4);
613         nw_dist = (ne rotated 90) * 0.5 blot_diameter;
614
615         fill bot z1{left}
616              .. (z1 + nw_dist){ne}
617              -- (z2 + nw_dist){ne}
618              .. top z2{right}
619              -- top z3{right}
620              .. (z3 - nw_dist){-ne}
621              -- (z4 - nw_dist){-ne}
622              .. bot z4{left}
623              -- cycle;
624
625         if hwid_hash > 2 slash_thick#:
626                 save th;
627
628                 th = slash_thick - blot_diameter;
629                 y6 = y7;
630                 y5 = y8;
631                 y3 - y7 = th;
632                 y5 - y1 = th;
633                 z6 - z5 = whatever * ne;
634                 z8 - z7 = whatever * ne;
635
636                 z5 = z1 + whatever * ne + th * (ne rotated -90);
637                 z8 = z4 + whatever * ne + th * (ne rotated 90);
638
639                 unfill z5
640                        -- z6
641                        -- z7
642                        -- z8
643                        -- cycle;
644         fi
645         labels (range 1 thru 10);
646 enddef;
647
648
649 fet_beginchar ("Whole slashhead", "s0slash");
650         draw_slash (4 slash_thick# + 0.5 staff_space#);
651
652         draw_staff (-2, 2, 0);
653 fet_endchar;
654
655
656 fet_beginchar ("Half slashhead", "s1slash");
657         draw_slash (3.0 slash_thick# + 0.15 staff_space#);
658
659         draw_staff (-2, 2, 0);
660 fet_endchar;
661
662
663 fet_beginchar ("Quarter slashhead", "s2slash");
664         draw_slash (1.5 slash_thick#);
665
666         draw_staff (-2, 2, 0);
667 fet_endchar;
668
669
670 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
671 %
672 % `thick' is the distance between the NE/SW parallel lines in the cross
673 % (distance between centres of lines) in multiples of stafflinethickness
674 %
675 def draw_cross (expr thick) =
676         save ne, nw;
677         save ne_dist, nw_dist, rt_dist, up_dist;
678         save crz_in, crz_out;
679         save thickness;
680         pair ne, nw;
681         pair ne_dist, nw_dist, rt_dist, up_dist;
682         path crz_in, crz_out;
683
684         pen_thick# := 1.2 stafflinethickness#;
685         thickness# := thick * stafflinethickness#;
686         define_pixels (thickness);
687         define_blacker_pixels (pen_thick);
688
689         pickup pencircle scaled pen_thick;
690
691         h := h - feta_shift;
692
693         top y3 = h;
694         ne = unitvector ((1, (2 h - pen_thick) / (w - pen_thick)));
695         rt x4 = w / 2;
696         y5 = 0;
697         z4 - z5 = whatever * ne;
698         x6 = 0;
699         z6 - z3 = whatever * ne;
700         z3 - z4 = whatever * (ne yscaled -1);
701
702         z4 - z3 = whatever * (ne) + (ne rotated -90) * thickness;
703
704
705         x1 = charwd / 2 - .5 pen_thick#;
706         z1 = whatever * ne
707              + thick / 2 * stafflinethickness# * (ne rotated -90);
708
709         % labels (1, 2, 3, 4, 5, 6);
710
711         nw = unitvector (z3 - z4);
712
713         up_dist = up * 0.5 pen_thick / cosd (angle (ne));
714         rt_dist = right * 0.5 pen_thick / sind (angle (ne));
715         nw_dist = (ne rotated 90) * 0.5 pen_thick;
716         ne_dist = (nw rotated -90) * 0.5 pen_thick;
717
718         x4' := x4;
719         x5' := x5;
720         y6' := y6;
721
722         x4 := hround (x4' + .5 pen_thick) - .5 pen_thick;
723         x5 := hfloor (x5' + xpart rt_dist) - xpart rt_dist;
724         y6 := vfloor (y6' + ypart up_dist) - ypart up_dist;
725
726         crz_out = (z6 + up_dist)
727                   -- (z3 + nw_dist){ne}
728                   .. (top z3)
729                   .. (z3 + ne_dist){-nw}
730                   -- (z4 + ne_dist){-nw}
731                   .. (rt z4)
732                   .. (z4 - nw_dist){-ne}
733                   -- (z5 + rt_dist);
734         crz_out := crz_out shifted (0, feta_shift)
735                    -- reverse crz_out yscaled -1 shifted (0, -feta_eps);
736         fill crz_out
737              -- reverse crz_out xscaled -1 shifted (-feta_eps, 0)
738              -- cycle;
739
740         if (thick > 1):
741                 x4 := hround (x4' - xpart rt_dist) + xpart rt_dist;
742                 x5 := hceiling (x5' - .5 pen_thick) + .5 pen_thick;
743                 y6 := vfloor (y6' - .5 pen_thick) + .5 pen_thick;
744
745                 crz_in = (bot z6){right}
746                          .. (z6 - nw_dist){ne}
747                          -- (z3 - up_dist)
748                          -- (z4 - rt_dist)
749                          -- (z5 + nw_dist){-ne}
750                          .. {down}(lft z5);
751                 crz_in := crz_in shifted (0, feta_shift)
752                           -- reverse crz_in yscaled -1 shifted (0, -feta_eps);
753                 unfill crz_in
754                        -- reverse crz_in xscaled -1 shifted (-feta_eps, 0)
755                        -- cycle;
756         fi
757
758         % ugh
759         currentpicture := currentpicture shifted (hround (w / 2), 0);
760
761         charwx := charwd;
762         charwy := y1 + feta_shift;
763
764         z12 = (charwx * hppp, y1 * vppp);
765
766         labels (12);
767 enddef;
768
769
770 fet_beginchar ("Whole Crossed notehead", "s0cross");
771         save wid, hei;
772
773         wid# := black_notehead_width# + 4 stafflinethickness#;
774         hei# := noteheight# + stafflinethickness#;
775
776         set_char_box (0, wid#, hei# / 2, hei# / 2);
777
778         draw_cross (3.75);
779
780         remember_pic := currentpicture;
781
782         draw_staff (-2, 2, 0);
783 fet_endchar;
784
785
786 if test > 0:
787         fet_beginchar ("Whole Crossed notehead", "s0cross");
788                 save wid, hei;
789
790                 wid# := black_notehead_width# + 4 stafflinethickness#;
791                 hei# := noteheight# + stafflinethickness#;
792
793                 set_char_box (0, wid#, hei# / 2, hei# / 2);
794
795                 currentpicture := remember_pic;
796
797                 draw_staff (-2, 2, 0.5);
798         fet_endchar;
799 fi;
800
801
802 fet_beginchar ("Half Crossed notehead", "s1cross");
803         save wid, hei;
804
805         wid# := black_notehead_width# + 2 stafflinethickness#;
806         hei# := noteheight# + stafflinethickness# / 2;
807
808         set_char_box (0, wid#, hei# / 2, hei# / 2);
809
810         draw_cross (3.0);
811
812         remember_pic := currentpicture;
813
814         draw_staff (-2, 2, 0);
815 fet_endchar;
816
817
818 if test > 0:
819         fet_beginchar ("Half Crossed notehead", "s1cross");
820                 save wid, hei;
821
822                 wid# := black_notehead_width# + 2 stafflinethickness#;
823                 hei# := noteheight# + stafflinethickness# / 2;
824
825                 set_char_box (0, wid#, hei# / 2, hei# / 2);
826
827                 currentpicture := remember_pic;
828
829                 draw_staff (-2, 2, 0.5);
830         fet_endchar;
831 fi;
832
833
834 fet_beginchar ("Crossed notehead", "s2cross");
835         wid# := black_notehead_width#;
836         hei# := noteheight#;
837         set_char_box (0, wid#, hei# / 2, hei# / 2);
838
839         draw_cross (1.0);
840
841         remember_pic := currentpicture;
842
843         draw_staff (-2, 2, 0);
844 fet_endchar;
845
846
847 if test > 0:
848         fet_beginchar ("Crossed notehead", "s2cross");
849                 wid# := black_notehead_width#;
850                 hei# := noteheight#;
851                 set_char_box (0, wid#, hei# / 2, hei# / 2);
852
853                 currentpicture := remember_pic;
854
855                 draw_staff (-2, 2, 0.5);
856         fet_endchar;
857 fi;
858
859
860 fet_beginchar ("X-Circled notehead", "s2xcircle");
861         save wid, hei;
862         save cthick, cxd, cyd, dy;
863
864         wid# := black_notehead_width# * sqrt (sqrt2);
865         hei# := noteheight# * sqrt (sqrt2);
866
867         set_char_box (0, wid#, hei# / 2, hei# / 2);
868
869         d := d - feta_space_shift;
870
871         cthick# := (1.2 + 1/4) * stafflinethickness#;
872         define_blacker_pixels (cthick);
873
874         cxd := w - cthick;
875         cyd := h + d - cthick / 2;
876
877         dy = .5 (h - d);
878
879         pickup pencircle scaled cthick;
880
881         fill fullcircle xscaled (cxd + cthick)
882                         yscaled (cyd + cthick)
883                         shifted (w / 2, dy);
884         unfill fullcircle xscaled (cxd - cthick)
885                           yscaled (cyd - cthick)
886                           shifted (w / 2, dy);
887
888         xpos := .5 cxd / sqrt2;
889         ypos := .5 cyd / sqrt2;
890
891         pickup penrazor scaled cthick rotated (angle (xpos, ypos) + 90);
892         draw (-xpos + w / 2, -ypos + dy)
893              -- (xpos + w / 2, ypos + dy);
894
895         pickup penrazor scaled cthick rotated (angle (xpos, -ypos) + 90);
896         draw (-xpos + w / 2, ypos + dy)
897              -- (xpos + w / 2, -ypos + dy);
898
899         charwx := charwd;
900         charwy := 0;
901
902         z12 = (charwx * hppp, charwy * vppp);
903         labels (12);
904
905         remember_pic := currentpicture;
906
907         draw_staff (-2, 2, 0);
908 fet_endchar;
909
910
911 if test > 0:
912         fet_beginchar ("X-Circled notehead", "s2xcircle");
913                 save wid, hei;
914                 save cthick, cxr, cyr;
915
916                 wid# := black_notehead_width# * sqrt (sqrt2);
917                 hei# := noteheight# * sqrt (sqrt2);
918
919                 set_char_box (0, wid#, hei# / 2, hei# / 2);
920
921                 currentpicture := remember_pic;
922
923                 draw_staff (-2, 2, 0.5);
924         fet_endchar;
925 fi;
926
927
928 %%%%%%%%
929 %
930 % SOLFA SHAPED NOTES
931 %
932 %
933 % Note: For whole and half notes, the `fill' curve (p_out) is offset from
934 %       the points that specify the outer geometry, because we need to add
935 %       the rounding.  In contrast, the inner curve is not offset, because
936 %       there is no rounding.
937 %
938 %       This means that to get a line of thick_factor * pen_thickness,
939 %       we need to offset the inner curve by
940 %
941 %         (thick_factor - 0.5) * pen_thickness
942 %
943 %       or by
944 %
945 %         (2 * thick_factor - 1) * half_pen_thickness
946 %
947 save solfa_pen_thick;
948 solfa_pen_thick# = 1.3 stafflinethickness#;
949 define_blacker_pixels (solfa_pen_thick);
950
951 save solfa_pen_radius;
952 solfa_pen_radius = 0.5 solfa_pen_thick;
953
954 save solfa_base_notewidth;
955 solfa_base_notewidth# := black_notehead_width#;
956
957 solfa_whole_width := 1.0;
958 solfa_half_width := 1.0;
959 solfa_quarter_width := 1.0;
960
961
962 %%% Do head
963 %
964 % Triangle with base parallel to staff lines.
965 %
966
967 def draw_do_head (expr width_factor, dir, thickness_factor) =
968         save p_in, p_out;
969         save left_dist, right_dist, bottom_dist;
970         path p_in, p_out;
971         pair left_dist, right_dist, bottom_dist;
972
973         set_char_box (0, width_factor * solfa_base_notewidth#,
974                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
975
976         bottom_thick_factor := 2 * thickness_factor - 1;
977         % no different thickness for left side if we want uniform thickness
978         if thickness_factor = 1:
979                 left_thick_factor := 1;
980         else:
981                 left_thick_factor := 0.7 * bottom_thick_factor;
982         fi
983
984         save pen_radius;
985         pen_radius := min (solfa_pen_radius,
986                            (h + d) / (3 * (1 + bottom_thick_factor)));
987
988         pickup pencircle scaled (2 * pen_radius);
989
990         bot y1 = -d;
991         y1 = y2;
992         lft x1 = 0;
993         rt x2 = w;
994         top y3 = h;
995         x3 = .5 [x1, x2];
996
997         left_dist = (unitvector (z3 - z1) rotated 90) * pen_radius;
998         right_dist = (unitvector (z2 - z3) rotated 90) * pen_radius;
999         bottom_dist = (0,1) * pen_radius;
1000
1001         save pa, pb, pc;
1002         path pa, pb, pc;
1003         save point_a, point_b, point_c;
1004         pair point_a, point_b, point_c;
1005
1006         pa := (z1 - left_thick_factor * left_dist)
1007               -- (z3 - left_thick_factor * left_dist);
1008         pb := (z1 + bottom_thick_factor * bottom_dist)
1009               -- (z2 + bottom_thick_factor * bottom_dist);
1010         pc := (z2 - right_dist)
1011               -- (z3 - right_dist);
1012
1013         point_a := pa intersectionpoint pb;
1014         point_b := pb intersectionpoint pc;
1015         point_c := pc intersectionpoint pa;
1016
1017         p_in := point_a
1018                 -- point_b
1019                 -- point_c
1020                 -- cycle;
1021
1022         p_out := bot z1
1023                  -- bot z2{right}
1024                  .. rt z2{up}
1025                  .. (z2 + right_dist){z3 - z2}
1026                  -- (z3 + right_dist){z3 - z2}
1027                  .. top z3{left}
1028                  .. (z3 + left_dist){z1 - z3}
1029                  -- (z1 + left_dist){z1 - z3}
1030                  .. lft z1{down}
1031                  .. {right}cycle;
1032
1033         labels (1, 2, 3);
1034
1035         charwx := charwd;
1036         charwy := -chardp + 0.5 stafflinethickness#;
1037         if dir = -1:
1038                 charwy := -charwy;
1039         fi;
1040 enddef;
1041
1042 save do_weight;
1043 do_weight := 2;
1044
1045
1046 fet_beginchar ("Whole dohead", "s0do");
1047         draw_do_head (solfa_whole_width, 1, do_weight);
1048         fill p_out;
1049         unfill p_in;
1050 fet_endchar;
1051
1052
1053 fet_beginchar ("Half dohead", "d1do");
1054         draw_do_head (solfa_half_width, -1, do_weight);
1055         fill p_out;
1056         unfill p_in;
1057 fet_endchar;
1058
1059
1060 fet_beginchar ("Half dohead", "u1do");
1061         draw_do_head (solfa_half_width, 1, do_weight);
1062         fill p_out;
1063         unfill p_in;
1064 fet_endchar;
1065
1066
1067 fet_beginchar ("Quarter dohead", "d2do");
1068         draw_do_head (solfa_quarter_width, -1, do_weight);
1069         fill p_out;
1070 fet_endchar;
1071
1072
1073 fet_beginchar ("Quarter dohead", "u2do");
1074         draw_do_head (solfa_quarter_width, 1, do_weight);
1075         fill p_out;
1076 fet_endchar;
1077
1078
1079 fet_beginchar ("Whole thin dohead", "s0doThin");
1080         draw_do_head (solfa_whole_width, 1, 1);
1081         fill p_out;
1082         unfill p_in;
1083 fet_endchar;
1084
1085
1086 fet_beginchar ("Half thin dohead", "d1doThin");
1087         draw_do_head (solfa_half_width, -1, 1);
1088         fill p_out;
1089         unfill p_in;
1090 fet_endchar;
1091
1092
1093 fet_beginchar ("Half thin dohead", "u1doThin");
1094         draw_do_head (solfa_half_width, 1, 1);
1095         fill p_out;
1096         unfill p_in;
1097 fet_endchar;
1098
1099
1100 fet_beginchar ("Quarter thin dohead", "d2doThin");
1101         draw_do_head (solfa_quarter_width, -1, 1);
1102         fill p_out;
1103 fet_endchar;
1104
1105
1106 fet_beginchar ("Quarter thin dohead", "u2doThin");
1107         draw_do_head (solfa_quarter_width, 1, 1);
1108         fill p_out;
1109 fet_endchar;
1110
1111
1112 %
1113 % re - flat top, curved bottom:
1114 %
1115 %   (0,h/2) {dir -90}
1116 %   .. (w/2,-h/2)
1117 %   .. {dir 90} (w,h/2)
1118 %   -- cycle;
1119 %
1120 % (broader along the base and with more vertical sides for half and
1121 % whole notes)
1122 %
1123 % Note: According to some shape-note singers, there should be no size
1124 %       differences for half and whole notes, contrary to the comment above.
1125 %       Consequently, we have made them all the same width.
1126 %
1127 % stem attachment: h/2
1128 %
1129 def draw_re_head (expr width_factor, dir, thickness_factor) =
1130         save p_in, p_out;
1131         path p_in, p_out;
1132
1133         set_char_box (0, width_factor * solfa_base_notewidth#,
1134                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
1135
1136         save offset;
1137         offset = (2 * thickness_factor - 1);
1138
1139         save curve_start;
1140         curve_start = 0.7;
1141
1142         save pen_radius;
1143
1144         pen_radius := min (solfa_pen_radius,
1145                            (h + d) * (1-curve_start) / (1+ offset));
1146
1147         pickup pencircle scaled (2 * pen_radius);
1148
1149         lft x1 = 0;
1150         top y1 = h;
1151         x2 = x1;
1152         y2 = curve_start [y3, y1];
1153         bot y3 = -d;
1154         x3 = .5 [x2, x4];
1155         rt x4 = w;
1156         y4 = y2;
1157         y5 = y1;
1158         x5 = x4;
1159
1160         labels (range 1 thru 5);
1161
1162         p_in := (z1 + pen_radius * (1, -1 * offset))
1163                 -- rt z2{down}
1164                 .. ((top z3) + (0, offset * pen_radius))
1165                 .. lft z4{up}
1166                 -- (z5 + pen_radius * (-1, -1 * offset))
1167                 -- cycle;
1168
1169         p_out := lft z1
1170                  -- lft z2{down}
1171                  .. bot z3
1172                  .. rt z4{up}
1173                  -- rt z5{up}
1174                  .. top z5{left}
1175                  -- top z1{left}
1176                  .. {down}cycle;
1177
1178         charwx := charwd;
1179         charwy := curve_start [-chardp, charht];
1180
1181         if dir = -1:
1182                 charwy := -charwy;
1183         fi;
1184 enddef;
1185
1186
1187 save re_weight;
1188 re_weight := 2;
1189
1190 fet_beginchar ("Whole rehead", "s0re");
1191         draw_re_head (solfa_whole_width, 1, re_weight);
1192         fill p_out;
1193         unfill p_in;
1194 fet_endchar;
1195
1196
1197 fet_beginchar ("Half up rehead", "u1re");
1198         draw_re_head (solfa_half_width, 1, re_weight);
1199         fill p_out;
1200         unfill p_in;
1201 fet_endchar;
1202
1203
1204 fet_beginchar ("Half down rehead", "d1re");
1205         draw_re_head (solfa_half_width, -1, re_weight);
1206         fill p_out;
1207         unfill p_in;
1208 fet_endchar;
1209
1210
1211 fet_beginchar ("Quarter up rehead", "u2re");
1212         draw_re_head (solfa_quarter_width, 1, re_weight);
1213         fill p_out;
1214 fet_endchar;
1215
1216
1217 fet_beginchar ("Quarter down rehead", "d2re");
1218         draw_re_head (solfa_quarter_width, -1, re_weight);
1219         fill p_out;
1220 fet_endchar;
1221
1222
1223 fet_beginchar ("Whole thin rehead", "s0reThin");
1224         draw_re_head (solfa_whole_width, 1, 1);
1225         fill p_out;
1226         unfill p_in;
1227 fet_endchar;
1228
1229
1230 fet_beginchar ("Half up thin rehead", "u1reThin");
1231         draw_re_head (solfa_half_width, 1, 1);
1232         fill p_out;
1233         unfill p_in;
1234 fet_endchar;
1235
1236
1237 fet_beginchar ("Half down thin rehead", "d1reThin");
1238         draw_re_head (solfa_half_width, -1, 1);
1239         fill p_out;
1240         unfill p_in;
1241 fet_endchar;
1242
1243
1244 fet_beginchar ("Quarter thin rehead", "u2reThin");
1245         draw_re_head (solfa_quarter_width, 1, 1);
1246         fill p_out;
1247 fet_endchar;
1248
1249
1250 fet_beginchar ("Quarter thin rehead", "d2reThin");
1251         draw_re_head (solfa_quarter_width, -1, 1);
1252         fill p_out;
1253 fet_endchar;
1254
1255
1256 %%%% mi head -- diamond shape
1257 %
1258 % two versions, depending on whether the `strong' lines are on the nw & se
1259 % or the ne & sw
1260 %
1261 def draw_mi_head (expr width_factor, thickness_factor, mirror) =
1262         save path_out, path_in;
1263         save ne_dist, se_dist, ne, se;
1264         save path_a, path_b, path_c, path_d;
1265         path path_out, path_in;
1266         pair ne_dist, se_dist, ne, se;
1267         path path_a, path_b, path_c, path_d;
1268         save inner_path;
1269         path inner_path;
1270
1271         set_char_box (0, width_factor * solfa_base_notewidth#,
1272                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
1273
1274         save offset;
1275         offset := 2 * thickness_factor - 1;
1276
1277         save note_diagonal;
1278
1279         note_diagonal := w / 2 ++ (h + d) / 2;
1280
1281         save pen_radius;
1282
1283         pen_radius := min (solfa_pen_radius,
1284                            .3 * note_diagonal / (1 + offset));
1285
1286         pickup pencircle scaled (2 * pen_radius);
1287
1288         lft x1 = 0;
1289         y1 = 0;
1290         bot y2 = -d;
1291         x2 = .5 [x1, x3];
1292         rt x3 = w;
1293         x4 = x2;
1294         y3 = y1;
1295         top y4 = h;
1296
1297         % inner sides are parallel to outer sides
1298         z6 - z5 = whatever * (z2 - z1);
1299         z8 - z7 = whatever * (z4 - z3);
1300         z8 - z5 = whatever * (z4 - z1);
1301         z7 - z6 = whatever * (z3 - z2);
1302
1303         ne = unitvector (z4 - z1);
1304         se = unitvector (z2 - z1);
1305
1306         ne_dist = (ne rotated 90) * pen_radius;
1307         se_dist = (se rotated 90) * pen_radius;
1308
1309         path_a := (z1 + se_dist)
1310                   -- (z2 + se_dist);
1311         path_b := (z2 + (ne_dist * offset))
1312                   -- (z3 + (ne_dist * offset));
1313         path_c := (z3 - se_dist)
1314                   -- (z4 - se_dist);
1315         path_d := (z4 - (ne_dist * offset))
1316                   -- (z1 - (ne_dist * offset));
1317
1318         z5 = path_a intersectionpoint path_d;
1319         z7 = path_b intersectionpoint path_c;
1320
1321         labels (range 1 thru 8);
1322
1323         inner_path := z5
1324                       -- z6
1325                       -- z7
1326                       -- z8
1327                       -- cycle;
1328
1329         if mirror:
1330                 path_in := inner_path;
1331         else:
1332                 path_in := inner_path reflectedabout (z2, z4);
1333         fi
1334
1335         path_out := lft z1 {down}
1336                     .. (z1 - se_dist){se}
1337                     -- (z2 - se_dist){se}
1338                     .. bot z2 {right}
1339                     .. (z2 - ne_dist){ne}
1340                     -- (z3 - ne_dist){ne}
1341                     .. rt z3 {up}
1342                     .. (z3 + se_dist){-se}
1343                     -- (z4 + se_dist){-se}
1344                     .. top z4 {left}
1345                     .. (z4 + ne_dist){-ne}
1346                     -- (z1 + ne_dist){-ne}
1347                     .. cycle;
1348 enddef;
1349
1350
1351 save mi_weight, mi_width;
1352 mi_weight := 2;
1353 mi_width := 1.2;
1354
1355 fet_beginchar ("Whole mihead", "s0mi");
1356         draw_mi_head (mi_width * solfa_whole_width, mi_weight, false);
1357         fill path_out;
1358         unfill path_in;
1359 fet_endchar;
1360
1361
1362 fet_beginchar ("Half mihead", "s1mi");
1363         draw_mi_head (mi_width * solfa_quarter_width, mi_weight, false);
1364         fill path_out;
1365         unfill path_in;
1366 fet_endchar;
1367
1368
1369 fet_beginchar ("Quarter mihead", "s2mi");
1370         draw_mi_head (mi_width * solfa_quarter_width, mi_weight, false);
1371         fill path_out;
1372 fet_endchar;
1373
1374
1375 fet_beginchar ("Whole mirror mihead", "s0miMirror");
1376         draw_mi_head (mi_width * solfa_whole_width, mi_weight, true);
1377         fill path_out;
1378         unfill path_in;
1379 fet_endchar;
1380
1381
1382 fet_beginchar ("Half  mirror mihead", "s1miMirror");
1383         draw_mi_head (mi_width * solfa_quarter_width, mi_weight, true);
1384         fill path_out;
1385         unfill path_in;
1386 fet_endchar;
1387
1388
1389 fet_beginchar ("Quarter mirror mihead", "s2miMirror");
1390         draw_mi_head (mi_width * solfa_quarter_width, mi_weight, true);
1391         fill path_out;
1392 fet_endchar;
1393
1394
1395 fet_beginchar ("Whole thin mihead", "s0miThin");
1396         draw_mi_head (mi_width * solfa_whole_width, 1, false);
1397         fill path_out;
1398         unfill path_in;
1399 fet_endchar;
1400
1401
1402 fet_beginchar ("Half thin mihead", "s1miThin");
1403         draw_mi_head (mi_width * solfa_quarter_width, 1, false);
1404         fill path_out;
1405         unfill path_in;
1406 fet_endchar;
1407
1408
1409 fet_beginchar ("Quarter thin mihead", "s2miThin");
1410         draw_mi_head (mi_width * solfa_quarter_width, 1, false);
1411         fill path_out;
1412 fet_endchar;
1413
1414
1415 %%%% fa head
1416 %
1417 % Right triangle, hypotenuse from nw to se corner.  Stem attaches on
1418 % vertical side in direction of horizontal side.
1419 %
1420 def draw_fa_head (expr width_factor, thickness_factor) =
1421         set_char_box (0, width_factor * solfa_base_notewidth#,
1422                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
1423
1424         save p_down_in, p_down_out, p_up_in, p_up_out, nw_dist, nw;
1425         path p_down_in, p_down_out, p_up_in, p_up_out;
1426         save path_a, path_b, path_c;
1427         path path_a, path_b, path_c;
1428         pair nw_dist, nw;
1429
1430         save offset;
1431         offset := 2 * thickness_factor - 1;
1432
1433         save pen_radius;
1434         pen_radius := min (solfa_pen_radius,
1435                            .33 * (h + d) / (1 + offset));
1436
1437         pickup pencircle scaled (2 * pen_radius);
1438
1439         lft x1 = 0;
1440         top y1 = h;
1441
1442         rt x2 = w;
1443         y2 = y1;
1444         bot y3 = -d;
1445         x3 = x2;
1446
1447         y4 = y3;
1448         x4 = x1;
1449
1450         labels (1, 2, 3, 4);
1451
1452         nw = unitvector (z1 - z3);
1453         nw_dist = (nw rotated 90) * pen_radius;
1454
1455         path_a := (z1 - (0,1) * offset * pen_radius)
1456                   -- (z2 - (0,1) * offset * pen_radius);
1457         path_b := (z2 - (1,0) * pen_radius)
1458                   -- (z3 - (1,0) * pen_radius);
1459         path_c := (z3 - nw_dist)
1460                   -- (z1 - nw_dist);
1461
1462         p_up_in := (path_a intersectionpoint path_b)
1463                    -- (path_b intersectionpoint path_c)
1464                    -- (path_c intersectionpoint path_a)
1465                    -- cycle;
1466
1467         p_up_out := lft z1{down}
1468                     .. (z1 + nw_dist){-nw}
1469                     -- (z3 + nw_dist){-nw}
1470                     .. bot z3{right}
1471                     .. rt z3{up}
1472                     -- rt z2{up}
1473                     .. top z2{left}
1474                     -- top z1{left}
1475                     .. cycle;
1476
1477         p_down_in := p_up_in rotated 180 shifted (w, 0);
1478         p_down_out := p_up_out rotated 180 shifted (w, 0);
1479
1480         charwy := 0.0;
1481         charwx := charwd;
1482 enddef;
1483
1484 save fa_weight;
1485 fa_weight := 1.75;
1486
1487 fet_beginchar ("Whole fa up head", "u0fa");
1488         draw_fa_head (solfa_whole_width, fa_weight);
1489         fill p_up_out;
1490         unfill p_up_in;
1491 fet_endchar;
1492
1493
1494 fet_beginchar ("Whole fa down head", "d0fa");
1495         draw_fa_head (solfa_whole_width, fa_weight);
1496         fill p_down_out;
1497         unfill p_down_in;
1498 fet_endchar;
1499
1500
1501 fet_beginchar ("half fa up head", "u1fa");
1502         draw_fa_head (solfa_half_width, fa_weight);
1503         fill p_up_out;
1504         unfill p_up_in;
1505 fet_endchar;
1506
1507
1508 fet_beginchar ("Half fa down head", "d1fa");
1509         draw_fa_head (solfa_half_width, fa_weight);
1510         fill p_down_out;
1511         unfill p_down_in;
1512 fet_endchar;
1513
1514
1515 fet_beginchar ("Quarter fa up head", "u2fa");
1516         draw_fa_head (solfa_quarter_width, fa_weight);
1517         fill p_up_out;
1518 fet_endchar;
1519
1520
1521 fet_beginchar ("Quarter fa down head", "d2fa");
1522         draw_fa_head (solfa_quarter_width, fa_weight);
1523         fill p_down_out;
1524 fet_endchar;
1525
1526
1527 fet_beginchar ("Whole thin fa up head", "u0faThin");
1528         draw_fa_head (solfa_whole_width, 1);
1529         fill p_up_out;
1530         unfill p_up_in;
1531 fet_endchar;
1532
1533
1534 fet_beginchar ("Whole thin fa down head", "d0faThin");
1535         draw_fa_head (solfa_whole_width, 1);
1536         fill p_down_out;
1537         unfill p_down_in;
1538 fet_endchar;
1539
1540
1541 fet_beginchar ("half thin fa up head", "u1faThin");
1542         draw_fa_head (solfa_half_width, 1);
1543         fill p_up_out;
1544         unfill p_up_in;
1545 fet_endchar;
1546
1547
1548 fet_beginchar ("Half thin fa down head", "d1faThin");
1549         draw_fa_head (solfa_half_width, 1);
1550         fill p_down_out;
1551         unfill p_down_in;
1552 fet_endchar;
1553
1554
1555 fet_beginchar ("Quarter thin fa up head", "u2faThin");
1556         draw_fa_head (solfa_quarter_width, 1);
1557         fill p_up_out;
1558 fet_endchar;
1559
1560
1561 fet_beginchar ("Quarter thin fa down head", "d2faThin");
1562         draw_fa_head (solfa_quarter_width, 1);
1563         fill p_down_out;
1564 fet_endchar;
1565
1566
1567
1568 %%%% sol head
1569 %
1570 % Note: sol head is the same shape as a standard music head, and doesn't
1571 %       vary from style to style.  However, width is constant with duration,
1572 %       so we can't just use the standard note font.
1573 %
1574 def draw_sol_head (expr filled) =
1575         draw_outside_ellipse (1.53 - puff_up_factor / 3.0, 34, 0.66, 0.17);
1576         if not filled:
1577           undraw_inside_ellipse (3.25, 33, 0.81, 2.5 stafflinethickness#);
1578         fi
1579         draw_staff (-2, 2, 0);
1580 enddef;
1581
1582 fet_beginchar ("Whole solhead", "s0sol");
1583         draw_sol_head ( false);
1584 fet_endchar;
1585
1586
1587 fet_beginchar ("Half solhead", "s1sol");
1588         draw_sol_head ( false);
1589 fet_endchar;
1590
1591
1592 fet_beginchar ("Quarter solhead", "s2sol");
1593         draw_sol_head ( true);
1594 fet_endchar;
1595
1596
1597 %%%% la head
1598 %
1599 %   Rectangle head
1600 %
1601 def draw_la_head (expr width_factor, thickness_factor) =
1602         set_char_box (0, width_factor * solfa_base_notewidth#,
1603                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
1604         save p_in, p_out;
1605         path p_in, p_out;
1606
1607         save offset;
1608         offset := 2 * thickness_factor - 1;
1609
1610         save pen_radius;
1611         pen_radius := min (solfa_pen_radius,
1612                            .35 * (h + d) / (1 + offset));
1613
1614         pickup pencircle scaled (2 * pen_radius);
1615
1616         lft x1 = 0;
1617         top y1 = h;
1618
1619         rt x2 = w;
1620         y2 = y1;
1621         bot y3 = -d;
1622         x3 = x2;
1623
1624         y4 = y3;
1625         x4 = x1;
1626
1627         labels (range 1 thru 4);
1628
1629         p_in := (z1 + pen_radius * (1, -offset))
1630                 -- (z2 + pen_radius * (-1, -offset))
1631                 -- (z3 + pen_radius * (-1, offset))
1632                 -- (z4 + pen_radius * (1, offset))
1633                 -- cycle;
1634
1635         p_out := top z1
1636                  -- top z2{right}
1637                  .. rt z2{down}
1638                  -- rt z3{down}
1639                  .. bot z3{left}
1640                  -- bot z4{left}
1641                  .. lft z4{up}
1642                  -- lft z1{up}
1643                  .. cycle;
1644 enddef;
1645
1646
1647 save la_weight;
1648 la_weight := 2;
1649
1650 fet_beginchar ("Whole lahead", "s0la");
1651         draw_la_head (solfa_whole_width, la_weight);
1652         fill p_out;
1653         unfill p_in;
1654 fet_endchar;
1655
1656
1657 fet_beginchar ("Half lahead", "s1la");
1658         draw_la_head (solfa_half_width, la_weight);
1659         fill p_out;
1660         unfill p_in;
1661 fet_endchar;
1662
1663
1664 fet_beginchar ("Quarter lahead", "s2la");
1665         draw_la_head (solfa_quarter_width, la_weight);
1666         fill p_out;
1667 fet_endchar;
1668
1669
1670 fet_beginchar ("Whole thin lahead", "s0laThin");
1671         draw_la_head (solfa_whole_width, 1);
1672         fill p_out;
1673         unfill p_in;
1674 fet_endchar;
1675
1676
1677 fet_beginchar ("Half thin lahead", "s1laThin");
1678         draw_la_head (solfa_half_width, 1);
1679         fill p_out;
1680         unfill p_in;
1681 fet_endchar;
1682
1683
1684 fet_beginchar ("Quarter lahead", "s2laThin");
1685         draw_la_head (solfa_quarter_width, 1);
1686         fill p_out;
1687 fet_endchar;
1688
1689
1690 %%%% ti head
1691 %
1692 %   `Snow-cone', V with rounded top.
1693 %
1694 def draw_ti_head (expr width_factor, dir, thickness_factor) =
1695         set_char_box (0, width_factor * solfa_base_notewidth#,
1696                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
1697         save p_in, p_out, p_top, p_top_in;
1698         path p_in, p_out, p_top, p_top_in;
1699         save cone_height;
1700         cone_height = 0.64;
1701
1702         save offset;
1703         offset := 2 * thickness_factor - 1;
1704
1705         save pen_radius;
1706         pen_radius := min (solfa_pen_radius,
1707                            .4 * (h + d) / (1 + offset));
1708
1709         pickup pencircle scaled (2 * pen_radius);
1710
1711         x1 = .5 [x2, x4];
1712         bot y1 = -d;
1713         lft x2 = 0;
1714         y2 = cone_height [y1, y3];
1715         rt x4 = w;
1716         y4 = y2;
1717         x3 = x1;
1718         top y3 = h;
1719         x5 = x1;
1720         y5 = y1 + offset * pen_radius;
1721
1722         labels (range 1 thru 4);
1723
1724         save nw_dist, sw_dist, nw, sw;
1725         pair nw_dist, sw_dist, nw, sw;
1726
1727         nw = unitvector (z2 - z1);
1728         sw = unitvector (z1 - z4);
1729
1730         nw_dist = (nw rotated 90) * pen_radius;
1731         sw_dist = (sw rotated 90) * pen_radius;
1732
1733         p_top := (z2 + nw * pen_radius)
1734                  .. (top z3){right}
1735                  .. (z4 - sw * pen_radius);
1736
1737         p_top_in := (z2 - nw * offset * pen_radius)
1738                     .. (z3 - (0,1) * pen_radius) {right}
1739                     .. (z4 + sw * offset * pen_radius);
1740
1741         save path_a, path_b;
1742         path path_a, path_b;
1743         path_a := z2
1744                   -- z5;
1745         path_b := z5
1746                   -- z4;
1747
1748         z6 = path_a intersectionpoint p_top_in;
1749         z7 = path_b intersectionpoint p_top_in;
1750
1751         p_in := z5
1752                 -- z6
1753                 .. bot z3
1754                 .. z7
1755                 -- cycle;
1756
1757         p_out := bot z1
1758                  .. (z1 + nw_dist)
1759                  -- (z2 + nw_dist)
1760                  .. lft z2
1761                  .. (z2 + nw * pen_radius){direction 0 of p_top}
1762                  & p_top
1763                  & {direction infinity of p_top}(z4 - sw * pen_radius)
1764                  .. rt z4
1765                  .. (z4 + sw_dist)
1766                  -- (z1 + sw_dist)
1767                  .. cycle;
1768
1769         charwx := charwd;
1770         charwy := cone_height [-chardp, charht];
1771         if dir = -1:
1772                 charwy := -charwy;
1773         fi;
1774 enddef;
1775
1776
1777 save ti_weight;
1778 ti_weight := 2;
1779
1780 fet_beginchar ("Whole up tihead", "s0ti");
1781         draw_ti_head (solfa_whole_width, 1, ti_weight);
1782         fill p_out;
1783         unfill p_in;
1784 fet_endchar;
1785
1786
1787 fet_beginchar ("Half up tihead", "u1ti");
1788         draw_ti_head (solfa_half_width, 1, ti_weight);
1789         fill p_out;
1790         unfill p_in;
1791 fet_endchar;
1792
1793
1794 fet_beginchar ("Half down tihead", "d1ti");
1795         draw_ti_head (solfa_half_width, -1, ti_weight);
1796         fill p_out;
1797         unfill p_in;
1798 fet_endchar;
1799
1800
1801 fet_beginchar ("Quarter up tihead", "u2ti");
1802         draw_ti_head (solfa_quarter_width, 1, ti_weight);
1803         fill p_out;
1804 fet_endchar;
1805
1806
1807 fet_beginchar ("Quarter down tihead", "d2ti");
1808         draw_ti_head (solfa_quarter_width, -1, ti_weight);
1809         fill p_out;
1810 fet_endchar;
1811
1812
1813 fet_beginchar ("Whole thin up tihead", "s0tiThin");
1814         draw_ti_head (solfa_whole_width, 1, 1);
1815         fill p_out;
1816         unfill p_in;
1817 fet_endchar;
1818
1819
1820 fet_beginchar ("Half thin up tihead", "u1tiThin");
1821         draw_ti_head (solfa_half_width, 1, 1);
1822         fill p_out;
1823         unfill p_in;
1824 fet_endchar;
1825
1826
1827 fet_beginchar ("Half thin down tihead", "d1tiThin");
1828         draw_ti_head (solfa_half_width, -1, 1);
1829         fill p_out;
1830         unfill p_in;
1831 fet_endchar;
1832
1833
1834 fet_beginchar ("Quarter thin up tihead", "u2tiThin");
1835         draw_ti_head (solfa_quarter_width, 1, 1);
1836         fill p_out;
1837 fet_endchar;
1838
1839
1840 fet_beginchar ("Quarter thin down tihead", "d2tiThin");
1841         draw_ti_head (solfa_quarter_width, -1, 1);
1842         fill p_out;
1843 fet_endchar;
1844
1845
1846 %%%%%%   Funk shape note heads
1847 %
1848 %  Funk heads are narrower than Aiken and Sacred Harp, so we need a new
1849 %  width.
1850 %
1851 funk_notehead_width := 0.75;
1852
1853
1854 %%%%%%   Funk do head
1855 %          Parabolic on one side, vertical line on other
1856 %          Has up and down shapes for *all* notes
1857 %
1858 def draw_Funk_do_head (expr width_factor, thickness_factor) =
1859         set_char_box (0, width_factor * solfa_base_notewidth#,
1860                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
1861
1862         save offset;
1863         offset := 2 * thickness_factor - 1;
1864
1865         save pen_radius;
1866         pen_radius := min (solfa_pen_radius,
1867                            .3 * (h + d) / (1 + offset));
1868
1869         pickup pencircle scaled (2 * pen_radius);
1870
1871         rt x1 = w;
1872         bot y1 = -d;
1873
1874         lft x2 = 0;
1875         y2 = 0.5 [y1, y3];
1876
1877         x3 = x1;
1878         top y3 = h;
1879
1880         x4 = x1 - pen_radius;
1881         y4 = y1 + offset * pen_radius;
1882
1883         y5 = y2;
1884         x5 = x2 + pen_radius;
1885
1886         x6 = x4;
1887         y6 = y3 - offset * pen_radius;
1888
1889         save p_up_in, p_up_out, p_down_in, p_down_out;
1890         path p_up_in, p_up_out, p_down_in, p_down_out;
1891
1892         p_down_in := z4{left}
1893                      ... z5{up}
1894                      ... z6{right}
1895                      -- cycle;
1896
1897         p_down_out := bot z1{left}
1898                       .. lft z2{up}
1899                       .. top z3{right}
1900                       .. rt z3{down}
1901                       -- rt z1{down}
1902                       .. cycle;
1903
1904         p_up_in := p_down_in rotated 180 shifted (w,0);
1905         p_up_out := p_down_out rotated 180 shifted (w,0);
1906
1907 enddef;
1908
1909
1910 save funk_do_weight;
1911 funk_do_weight := 1.7;
1912
1913 fet_beginchar ("Whole up Funk dohead", "u0doFunk");
1914         draw_Funk_do_head (funk_notehead_width, funk_do_weight);
1915         fill p_up_out;
1916         unfill p_up_in;
1917 fet_endchar;
1918
1919
1920 fet_beginchar ("Whole down Funk dohead", "d0doFunk");
1921         draw_Funk_do_head (funk_notehead_width, funk_do_weight);
1922         fill p_down_out;
1923         unfill p_down_in;
1924 fet_endchar;
1925
1926
1927 fet_beginchar ("Half up Funk dohead", "u1doFunk");
1928         draw_Funk_do_head (funk_notehead_width, funk_do_weight);
1929         fill p_up_out;
1930         unfill p_up_in;
1931 fet_endchar;
1932
1933
1934 fet_beginchar ("Half down Funk dohead", "d1doFunk");
1935         draw_Funk_do_head (funk_notehead_width, funk_do_weight);
1936         fill p_down_out;
1937         unfill p_down_in;
1938 fet_endchar;
1939
1940
1941 fet_beginchar ("Quarter up Funk dohead", "u2doFunk");
1942         draw_Funk_do_head (funk_notehead_width, funk_do_weight);
1943         fill p_up_out;
1944 fet_endchar;
1945
1946
1947 fet_beginchar ("Quarter down Funk dohead", "d2doFunk");
1948         draw_Funk_do_head (funk_notehead_width, funk_do_weight);
1949         fill p_down_out;
1950 fet_endchar;
1951
1952
1953 %%%%%%  Funk re head
1954 %       Arrowhead shape.
1955 %       Has up and down shapes for *all* notes
1956 %
1957 def draw_Funk_re_head (expr width_factor, thickness_factor) =
1958         set_char_box (0, width_factor * solfa_base_notewidth#,
1959                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
1960
1961         save offset;
1962         offset := 2 * thickness_factor - 1;
1963
1964         save pen_radius;
1965         pen_radius := min (solfa_pen_radius,
1966                            .3 * (h + d) / (1 + offset));
1967
1968         pickup pencircle scaled (2 * pen_radius);
1969
1970         save curve_in;
1971         curve_in := 0.9;
1972
1973         lft x1 = 0;
1974         y1 := 0.5 [y2, y4];
1975
1976         rt x2 = w;
1977         top y2 = h;
1978
1979         x3 := curve_in [x1, x2];
1980         y3 := y1;
1981
1982         x4 = x2;
1983         bot y4 = -d;
1984
1985         z6 = lft z3;
1986
1987         save ne, se, ne_perp, se_perp;
1988         pair ne, se, ne_perp, se_perp;
1989
1990         ne := unitvector (z2 - z1);
1991         se := unitvector (z4 - z1);
1992         ne_perp := ne rotated 90;
1993         se_perp := se rotated 90;
1994
1995         save path_a, path_b, path_c, path_d;
1996         path path_a, path_b, path_c, path_d;
1997         save arrow_a_perp, arrow_b_perp;
1998         pair arrow_a_perp, arrow_b_perp;
1999
2000
2001         path_d := z2 .. z3{down} .. z4;
2002         arrow_a_perp = unitvector (direction 0 of path_d rotated 90)
2003                        * pen_radius;
2004         arrow_b_perp = unitvector (direction 2 of path_d rotated 90)
2005                        * pen_radius;
2006
2007         path_b := (z1 + se_perp * pen_radius)
2008                   -- z4 + se_perp * offset * pen_radius;
2009         path_a := (z1 - ne_perp * pen_radius)
2010                   -- z2 - ne_perp * offset * pen_radius;
2011         path_c := z2 - arrow_a_perp
2012                   .. z6{down}
2013                   .. z4 - arrow_b_perp;
2014
2015         z5 = path_a intersectionpoint path_b;
2016         z7 = path_a intersectionpoint path_c;
2017         z8 = path_b intersectionpoint path_c;
2018
2019         save p_up_in, p_down_in, p_up_out, p_down_out;
2020         path p_up_in, p_down_in, p_up_out, p_down_out;
2021
2022         p_down_in := z5
2023                      -- z7
2024                      .. z6{down}
2025                      .. z8
2026                      -- cycle;
2027
2028         p_down_out := lft z1{up}
2029                       .. (z1 + ne_perp * pen_radius){ne}
2030                       -- (z2 + ne_perp * pen_radius){ne}
2031                       .. top z2 {right}
2032                       .. rt z2{down}
2033                       .. (z2 + arrow_a_perp)
2034                       .. rt z3{down}
2035                       .. (z4 + arrow_b_perp)
2036                       .. rt z4{down}
2037                       .. bot z4 {left}
2038                       .. z4 - se_perp * pen_radius
2039                       -- z1 - se_perp * pen_radius
2040                       .. cycle;
2041
2042         p_up_in := p_down_in rotated 180 shifted (w, 0);
2043         p_up_out := p_down_out rotated 180 shifted (w, 0);
2044
2045 enddef;
2046
2047
2048 save funk_re_weight;
2049 funk_re_weight = 1.7;
2050
2051 fet_beginchar ("Whole up Funk rehead", "u0reFunk");
2052         draw_Funk_re_head (funk_notehead_width, funk_re_weight);
2053         fill p_up_out;
2054         unfill p_up_in;
2055 fet_endchar;
2056
2057
2058 fet_beginchar ("Whole down Funk rehead", "d0reFunk");
2059         draw_Funk_re_head (funk_notehead_width, funk_re_weight);
2060         fill p_down_out;
2061         unfill p_down_in;
2062 fet_endchar;
2063
2064
2065 fet_beginchar ("Half up Funk rehead", "u1reFunk");
2066         draw_Funk_re_head (funk_notehead_width, funk_re_weight);
2067         fill p_up_out;
2068         unfill p_up_in;
2069 fet_endchar;
2070
2071
2072 fet_beginchar ("Half down Funk rehead", "d1reFunk");
2073         draw_Funk_re_head (funk_notehead_width, funk_re_weight);
2074         fill p_down_out;
2075         unfill p_down_in;
2076 fet_endchar;
2077
2078
2079 fet_beginchar ("Quarter up Funk rehead", "u2reFunk");
2080         draw_Funk_re_head (funk_notehead_width, funk_re_weight);
2081         fill p_up_out;
2082 fet_endchar;
2083
2084
2085 fet_beginchar ("Quarter down Funk rehead", "d2reFunk");
2086         draw_Funk_re_head (funk_notehead_width, funk_re_weight);
2087         fill p_down_out;
2088 fet_endchar;
2089
2090
2091 %%%%%%  Funk mi head
2092 %       Diamond shape
2093 %       Has up and down shapes for all hollow notes
2094 %
2095 save funk_mi_width, funk_mi_weight;
2096 funk_mi_width := 1.2;
2097 funk_mi_weight := 1.9;
2098
2099 fet_beginchar ("Whole up Funk mihead", "u0miFunk");
2100         draw_mi_head (funk_mi_width * funk_notehead_width,
2101                       funk_mi_weight, false);
2102         fill path_out;
2103         unfill path_in;
2104 fet_endchar;
2105
2106
2107 fet_beginchar ("Whole down Funk mihead", "d0miFunk");
2108         draw_mi_head (funk_mi_width * funk_notehead_width,
2109                       funk_mi_weight, true);
2110         fill path_out;
2111         unfill path_in;
2112 fet_endchar;
2113
2114
2115 fet_beginchar ("Half up Funk mihead", "u1miFunk");
2116         draw_mi_head (funk_mi_width * funk_notehead_width,
2117                       funk_mi_weight, false);
2118         fill path_out;
2119         unfill path_in;
2120 fet_endchar;
2121
2122
2123 fet_beginchar ("Half down Funk mihead", "d1miFunk");
2124         draw_mi_head (funk_mi_width * funk_notehead_width,
2125                       funk_mi_weight, true);
2126         fill path_out;
2127         unfill path_in;
2128 fet_endchar;
2129
2130
2131 fet_beginchar ("Quarter Funk mihead", "s2miFunk");
2132         draw_mi_head (funk_mi_width * funk_notehead_width,
2133                       funk_mi_weight, false);
2134         fill path_out;
2135 fet_endchar;
2136
2137
2138 %%%%%%  Funk fa
2139 %       Triangle shape
2140 %       Does it rotate for whole notes?
2141 %       Same as other shape note systems
2142 %       Need special notes because of special width
2143 %
2144 save funk_fa_weight;
2145 funk_fa_weight := 1.9;
2146
2147 fet_beginchar ("Whole up Funk fahead", "u0faFunk");
2148         draw_fa_head (funk_notehead_width, funk_fa_weight);
2149         fill p_up_out;
2150         unfill p_up_in;
2151 fet_endchar;
2152
2153
2154 fet_beginchar ("Whole down Funk fahead", "d0faFunk");
2155         draw_fa_head (funk_notehead_width, funk_fa_weight);
2156         fill p_down_out;
2157         unfill p_down_in;
2158 fet_endchar;
2159
2160
2161 fet_beginchar ("Half up Funk fahead", "u1faFunk");
2162         draw_fa_head (funk_notehead_width, funk_fa_weight);
2163         fill p_up_out;
2164         unfill p_up_in;
2165 fet_endchar;
2166
2167
2168 fet_beginchar ("Half down Funk fahead", "d1faFunk");
2169         draw_fa_head (funk_notehead_width, funk_fa_weight);
2170         fill p_down_out;
2171         unfill p_down_in;
2172 fet_endchar;
2173
2174
2175 fet_beginchar ("Quarter up Funk fahead", "u2faFunk");
2176         draw_fa_head (funk_notehead_width, funk_fa_weight);
2177         fill p_up_out;
2178 fet_endchar;
2179
2180
2181 fet_beginchar ("Quarter down Funk fahead", "d2faFunk");
2182         draw_fa_head (funk_notehead_width, funk_fa_weight);
2183         fill p_down_out;
2184 fet_endchar;
2185
2186
2187 %%%%%%  Funk sol head is the same as the others
2188 %       Need special character because of skinnier head
2189 %
2190 def draw_Funk_sol_head (expr filled) =
2191 begingroup
2192         save noteheight;
2193         noteheight# := solfa_noteheight#;
2194         draw_outside_ellipse (1.2, 34, 0.71, 0.);
2195         if not filled:
2196           undraw_inside_ellipse (1.9, 33, 0.74, 5.5 stafflinethickness#);
2197         fi
2198         draw_staff (-2, 2, 0);
2199 endgroup
2200 enddef;
2201
2202
2203 fet_beginchar ("Whole Funk solhead", "s0solFunk");
2204         draw_Funk_sol_head ( false);
2205 fet_endchar;
2206
2207
2208 fet_beginchar ("Half Funk solhead", "s1solFunk");
2209         draw_Funk_sol_head ( false);
2210 fet_endchar;
2211
2212
2213 fet_beginchar ("Quarter Funk solhead", "s2solFunk");
2214         draw_Funk_sol_head ( true);
2215 fet_endchar;
2216
2217
2218 %%%%%%  Funk la head
2219 %       Rectangle head
2220 %       Same as for other shape notes
2221 %       Smaller width requires special characters
2222 %
2223 save funk_la_weight;
2224 funk_la_weight := 1.9;
2225
2226 fet_beginchar ("Whole Funk lahead", "s0laFunk");
2227         draw_la_head (funk_notehead_width, funk_notehead_width);
2228         fill p_out;
2229         unfill p_in;
2230 fet_endchar;
2231
2232
2233 fet_beginchar ("Half Funk lahead", "s1laFunk");
2234         draw_la_head (funk_notehead_width, funk_notehead_width);
2235         fill p_out;
2236         unfill p_in;
2237 fet_endchar;
2238
2239
2240 fet_beginchar ("Quarter Funk lahead", "s2laFunk");
2241         draw_la_head (funk_notehead_width, funk_notehead_width);
2242         fill p_out;
2243 fet_endchar;
2244
2245
2246 %%%%%%  Funk ti head
2247 %       `Sideways snow cone'.
2248 %       Rotates for all notes.
2249 %
2250 def draw_Funk_ti_head (expr width_factor, thickness_factor) =
2251         set_char_box (0, width_factor * solfa_base_notewidth#,
2252                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
2253         save cone_width;
2254         cone_width = 0.8;
2255
2256         save offset;
2257         offset := 2 * thickness_factor - 1;
2258
2259         save pen_radius;
2260         pen_radius := min (solfa_pen_radius,
2261                            .33 * (h + d) / (1 + offset));
2262
2263         pickup pencircle scaled (2 * pen_radius);
2264
2265         lft x1 = 0;
2266         y1 = .5 [y2, y4];
2267
2268         x2 = cone_width [x1, x3];
2269         top y2 = h;
2270
2271         rt x3 = w;
2272         y3 = y1;
2273
2274         x4 = x2;
2275         bot y4 = -d;
2276
2277         save nw_dist, sw_dist, ne, se;
2278         pair nw_dist, sw_dist, ne, se;
2279
2280         ne = unitvector (z2 - z1);
2281         se = unitvector (z4 - z1);
2282
2283         nw_dist = (ne rotated 90) * pen_radius ;
2284         sw_dist = (se rotated -90) * pen_radius;
2285
2286         save path_a, path_b;
2287         path path_a, path_b;
2288         path_a := z1 - nw_dist
2289                   -- z2 - offset * nw_dist;
2290         path_b := z1 - sw_dist
2291                   -- z4 - offset * sw_dist;
2292
2293         save path_right, path_right_in;
2294         path path_right, path_right_in;
2295         path_right := (z2 + ne * pen_radius)
2296                       .. (rt z3){down}
2297                       .. (z4 + se * pen_radius);
2298
2299         path_right_in := (z2 - ne * pen_radius)
2300                          .. lft z3{down}
2301                          .. (z4 - se * pen_radius);
2302
2303         z5 = path_a intersectionpoint path_b;
2304         z6 = path_a intersectionpoint path_right_in;
2305         z7 = path_b intersectionpoint path_right_in;
2306
2307         save p_up_in, p_down_in, p_up_out, p_down_out;
2308         path p_up_in, p_down_in, p_up_out, p_down_out;
2309
2310         p_down_in := z5
2311                      -- z6
2312                      .. lft z3
2313                      .. z7
2314                      -- cycle;
2315
2316         p_down_out := lft z1
2317                       .. (z1 + nw_dist)
2318                       -- (z2 + nw_dist)
2319                       .. top z2
2320                       .. (z2 + ne * pen_radius){direction 0 of path_right}
2321                       & path_right
2322                       & {direction infinity of path_right}(z4 + se * pen_radius)
2323                       .. bot z4
2324                       .. (z4 + sw_dist)
2325                       -- (z1 + sw_dist)
2326                       .. cycle;
2327
2328         p_up_in := p_down_in rotated 180 shifted (w, 0);
2329         p_up_out := p_down_out rotated 180 shifted (w, 0);
2330 enddef;
2331
2332
2333 save funk_ti_weight;
2334 funk_ti_weight := 1.6;
2335
2336 fet_beginchar ("Whole up Funk tihead", "u0tiFunk");
2337         draw_Funk_ti_head (funk_notehead_width, funk_ti_weight);
2338         fill p_up_out;
2339         unfill p_up_in;
2340 fet_endchar;
2341
2342
2343 fet_beginchar ("Whole down Funk tihead", "d0tiFunk");
2344         draw_Funk_ti_head (funk_notehead_width, funk_ti_weight);
2345         fill p_down_out;
2346         unfill p_down_in;
2347 fet_endchar;
2348
2349
2350 fet_beginchar ("Half up Funk tihead", "u1tiFunk");
2351         draw_Funk_ti_head (funk_notehead_width, funk_ti_weight);
2352         fill p_up_out;
2353         unfill p_up_in;
2354 fet_endchar;
2355
2356
2357 fet_beginchar ("Half down Funk tihead", "d1tiFunk");
2358         draw_Funk_ti_head (funk_notehead_width, funk_ti_weight);
2359         fill p_down_out;
2360         unfill p_down_in;
2361 fet_endchar;
2362
2363
2364 fet_beginchar ("Quarter up Funk tihead", "u2tiFunk");
2365         draw_Funk_ti_head (funk_notehead_width, funk_ti_weight);
2366         fill p_up_out;
2367 fet_endchar;
2368
2369
2370 fet_beginchar ("Quarter down Funk tihead", "d2tiFunk");
2371         draw_Funk_ti_head (funk_notehead_width, funk_ti_weight);
2372         fill p_down_out;
2373 fet_endchar;
2374
2375
2376 %%%%%%   Walker shape note heads
2377 %
2378 % Walker heads are narrow like Funk heads, so use funk_notehead_width.
2379 %
2380
2381 %%%%%%   Walker do head
2382 %
2383 % Trapezoid, with largest side on stem side
2384 %
2385 def draw_Walker_do_head (expr width_factor, dir, thickness_factor) =
2386         set_char_box (0, width_factor * solfa_base_notewidth#,
2387                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
2388
2389         pickup pencircle scaled solfa_pen_thick;
2390
2391         save offset;
2392         offset := 2 * thickness_factor - 1;
2393
2394         % adjust width so stem can be centered
2395         if .5w <> good.x .5w: change_width; fi
2396
2397         save scaling;
2398
2399         scaling# = charwd / w;
2400
2401         save inset;
2402         inset := 0.25;
2403
2404         x1 = inset [x4, x3];
2405         top y1 = h;
2406
2407         x2 = inset [x3, x4];
2408         y2 = y1;
2409
2410         bot y3 = -d;
2411         rt x3 = w;
2412
2413         y4 = y3;
2414         lft x4 = 0;
2415
2416         labels (range 1 thru 4);
2417
2418         save left_dir, left_perp, right_dir, right_perp;
2419         pair left_dir, left_perp, right_dir, right_perp;
2420
2421         left_dir = unitvector(z1 - z4);
2422         left_perp = (left_dir rotated 90) * solfa_pen_radius;
2423         right_dir = unitvector(z3 - z2);
2424         right_perp = (right_dir rotated 90) * solfa_pen_radius;
2425
2426         save path_a, path_b, path_c, path_d;
2427         path path_a, path_b, path_c, path_d;
2428
2429         path_a := (z4 - left_perp)
2430                   -- (z1 - left_perp);
2431         path_b := (z1 - (0, offset*solfa_pen_radius))
2432                   -- (z2 - (0, offset*solfa_pen_radius));
2433         path_c := (z2 - right_perp)
2434                   -- (z3 - right_perp);
2435         path_d := (z3 + (0, offset*solfa_pen_radius))
2436                   -- (z4 + (0, offset*solfa_pen_radius));
2437
2438         save p_in, p_out;
2439         path p_in, p_out;
2440
2441         p_in := (path_a intersectionpoint path_b)
2442                 -- (path_b intersectionpoint path_c)
2443                 -- (path_c intersectionpoint path_d)
2444                 -- (path_d intersectionpoint path_a)
2445                 -- cycle;
2446
2447         p_out := top z1{right}
2448                  -- top z2{right}
2449                  .. z2 + right_perp {right_dir}
2450                  -- z3 + right_perp {right_dir}
2451                  .. bot z3{left}
2452                  -- bot z4{left}
2453                  .. z4 + left_perp {left_dir}
2454                  .. z1 + left_perp {left_dir}
2455                  .. cycle;
2456
2457         charwx := scaling# * (w/2 + solfa_pen_radius);
2458         charwy := scaling# * y2 ;
2459
2460         if dir = 1:
2461                 p_in := p_in rotated 180 shifted (w,0);
2462                 p_out := p_out rotated 180 shifted (w,0);
2463         fi;
2464 enddef;
2465
2466
2467 save walker_do_weight;
2468 walker_do_weight := 1.5;
2469
2470 fet_beginchar ("Whole Walker dohead", "s0doWalker");
2471         draw_Walker_do_head (funk_notehead_width, 0, walker_do_weight);
2472         fill p_out;
2473         unfill p_in;
2474 fet_endchar;
2475
2476
2477 fet_beginchar ("Half up Walker dohead", "u1doWalker");
2478         draw_Walker_do_head (funk_notehead_width, 1, walker_do_weight);
2479         fill p_out;
2480         unfill p_in;
2481 fet_endchar;
2482
2483
2484 fet_beginchar ("Half down Walker dohead", "d1doWalker");
2485         draw_Walker_do_head (funk_notehead_width, 0, walker_do_weight);
2486         fill p_out;
2487         unfill p_in;
2488 fet_endchar;
2489
2490
2491 fet_beginchar ("Quarter up Walker dohead", "u2doWalker");
2492         draw_Walker_do_head (funk_notehead_width, 1, walker_do_weight);
2493         fill p_out;
2494 fet_endchar;
2495
2496
2497 fet_beginchar ("Quarter down Walker dohead", "d2doWalker");
2498         draw_Walker_do_head (funk_notehead_width, 0, walker_do_weight);
2499         fill p_out;
2500 fet_endchar;
2501
2502
2503 %%%%%%   Walker re head
2504 %          Parabolic on one side, shallow parabola on other
2505 %          Has up and down shapes for *all* notes
2506 %
2507 def draw_Walker_re_head (expr width_factor, thickness_factor) =
2508         set_char_box (0, width_factor * solfa_base_notewidth#,
2509                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
2510
2511         save offset;
2512         offset := 2 * thickness_factor - 1;
2513
2514         save pen_radius;
2515         pen_radius := min (solfa_pen_radius,
2516                            .3 * (h + d) / (1 + offset));
2517
2518         pickup pencircle scaled (2 * pen_radius);
2519
2520         save dish_factor;
2521         dish_factor := 0.20;
2522
2523         rt x1 = w;
2524         bot y1 = -d;
2525
2526         lft x2 = 0;
2527         y2 = 0.5 [y1, y3];
2528
2529         top y3 = h;
2530         x3 = x1;
2531
2532         x4 = dish_factor [x1, x2];
2533         y4 = y2;
2534
2535         x5 = x1;
2536         y5 = y1 + offset * pen_radius;
2537
2538         y6 = y2;
2539         x6 = x2 + pen_radius;
2540
2541         x7 = x3;
2542         y7 = y3 - offset * pen_radius;
2543
2544         y8 = y4;
2545         x8 = x4 - pen_radius;
2546
2547         save path_a, path_d;
2548         path path_a, path_d;
2549
2550         save p_a_start_dir, p_a_end_dir, p_a_start_perp, p_a_end_perp;
2551         pair p_a_start_dir, p_a_end_dir, p_a_start_perp, p_a_end_perp;
2552
2553         path_a := z3 .. z4{down} .. z1;
2554
2555         p_a_start_dir := unitvector(direction 0 of path_a);
2556         p_a_end_dir := unitvector(direction infinity of path_a);
2557         p_a_start_perp := (p_a_start_dir rotated 90) * pen_radius;
2558         p_a_end_perp := (p_a_end_dir rotated 90) * pen_radius;
2559
2560         path_d := (z3 - p_a_start_perp){p_a_start_dir}
2561                   .. z4 {down}
2562                   ..(z1 - p_a_end_perp){p_a_end_dir};
2563
2564         save path_b, path_c;
2565         path path_b, path_c;
2566
2567         path_b := z5 {left} .. z6{up};
2568         path_c := z7 {left} .. z6{down};
2569
2570         z9 = path_d intersectionpoint path_b;
2571         z10 = path_d intersectionpoint path_c;
2572
2573         labels (range 1 thru 4);
2574
2575         save p_up_in, p_up_out, p_down_in, p_down_out;
2576         path p_up_in, p_up_out, p_down_in, p_down_out;
2577
2578         p_down_in := z6{up}
2579                      ... {right} z10 {p_a_start_dir}
2580                      .. z8{down}
2581                      .. {p_a_end_dir} z9 {left}
2582                      ... cycle;
2583
2584         p_down_out := lft z2{up}
2585                       .. top z3{right}
2586                       .. rt z3
2587                       .. (z3 + p_a_start_perp){p_a_start_dir}
2588                       .. rt z4{down}
2589                       .. (z1 + p_a_end_perp) {p_a_end_dir}
2590                       .. rt z1
2591                       .. bot z1 {left}
2592                       .. cycle;
2593
2594         p_up_in := p_down_in rotated 180 shifted (w,0);
2595         p_up_out := p_down_out rotated 180 shifted (w,0);
2596 enddef;
2597
2598
2599 save walker_re_weight;
2600 walker_re_weight := 1.2;
2601
2602 fet_beginchar ("Whole Walker rehead", "s0reWalker");
2603         draw_Walker_re_head (funk_notehead_width, walker_re_weight);
2604         fill p_down_out;
2605         unfill p_down_in;
2606 fet_endchar;
2607
2608
2609 fet_beginchar ("Half up Walker rehead", "u1reWalker");
2610         draw_Walker_re_head (funk_notehead_width, walker_re_weight);
2611         fill p_up_out;
2612         unfill p_up_in;
2613 fet_endchar;
2614
2615
2616 fet_beginchar ("Half down Walker rehead", "d1reWalker");
2617         draw_Walker_re_head (funk_notehead_width, walker_re_weight);
2618         fill p_down_out;
2619         unfill p_down_in;
2620 fet_endchar;
2621
2622
2623 fet_beginchar ("Quarter up Walker rehead", "u2reWalker");
2624         draw_Walker_re_head (funk_notehead_width, walker_re_weight);
2625         fill p_up_out;
2626 fet_endchar;
2627
2628
2629 fet_beginchar ("Quarter down Walker rehead", "d2reWalker");
2630         draw_Walker_re_head (funk_notehead_width, walker_re_weight);
2631         fill p_down_out;
2632 fet_endchar;
2633
2634
2635 %%%%%%  Walker mi head
2636 %       Diamond shape
2637 %       Symmetric for all hollow notes
2638 %
2639 save walker_mi_width, walker_mi_weight;
2640 walker_mi_width := 1.2;
2641 walker_mi_weight := 1.5;
2642
2643 fet_beginchar ("Whole Walker mihead", "s0miWalker");
2644         draw_mi_head (walker_mi_width * funk_notehead_width,
2645                       walker_mi_weight, true);
2646         fill path_out;
2647         unfill path_in;
2648 fet_endchar;
2649
2650
2651 fet_beginchar ("Half Walker mihead", "s1miWalker");
2652         draw_mi_head (walker_mi_width * funk_notehead_width,
2653                       walker_mi_weight, true);
2654         fill path_out;
2655         unfill path_in;
2656 fet_endchar;
2657
2658
2659 fet_beginchar ("Quarter Walker mihead", "s2miWalker");
2660         draw_mi_head (walker_mi_width * funk_notehead_width,
2661                       walker_mi_weight, true);
2662         fill path_out;
2663 fet_endchar;
2664
2665
2666 %%%%%%  Walker fa
2667 %       Triangle shape
2668 %       Does not rotate for whole notes
2669 %       Whole rotation is different from Funk, so special notes
2670
2671 %%%%%%  Funk sol head is the same as the others
2672 %       Need special character because of skinnier head
2673 %
2674 save walker_fa_weight;
2675 walker_fa_weight := 1.5;
2676
2677 fet_beginchar ("Whole Walker fahead", "s0faWalker");
2678         draw_fa_head (funk_notehead_width, walker_fa_weight);
2679         fill p_down_out;
2680         unfill p_down_in;
2681 fet_endchar;
2682
2683
2684 fet_beginchar ("Half up Walker fahead", "u1faWalker");
2685         draw_fa_head (funk_notehead_width, walker_fa_weight);
2686         fill p_up_out;
2687         unfill p_up_in;
2688 fet_endchar;
2689
2690
2691 fet_beginchar ("Half down Walker fahead", "d1faWalker");
2692         draw_fa_head (funk_notehead_width, walker_fa_weight);
2693         fill p_down_out;
2694         unfill p_down_in;
2695 fet_endchar;
2696
2697
2698 fet_beginchar ("Quarter up Walker fahead", "u2faWalker");
2699         draw_fa_head (funk_notehead_width, walker_fa_weight);
2700         fill p_up_out;
2701 fet_endchar;
2702
2703
2704 fet_beginchar ("Quarter down Walker fahead", "d2faWalker");
2705         draw_fa_head (funk_notehead_width, walker_fa_weight);
2706         fill p_down_out;
2707 fet_endchar;
2708
2709
2710 %%%%%%  Walker sol
2711 %       Same as Funk, no special notes
2712 %
2713
2714 %%%%%%  Walker la head
2715 %       Rectcangle head
2716 %       Lighter weight requires separate notes
2717 %
2718 save walker_la_weight;
2719 walker_la_weight := 1.5;
2720
2721 fet_beginchar ("Whole Walker lahead", "s0laWalker");
2722         draw_la_head (funk_notehead_width, walker_la_weight);
2723         fill p_out;
2724         unfill p_in;
2725 fet_endchar;
2726
2727
2728 fet_beginchar ("Half Funk lahead", "s1laWalker");
2729         draw_la_head (funk_notehead_width, walker_la_weight);
2730         fill p_out;
2731         unfill p_in;
2732 fet_endchar;
2733
2734
2735 fet_beginchar ("Quarter Funk lahead", "s2laWalker");
2736         draw_la_head (funk_notehead_width, walker_la_weight);
2737         fill p_out;
2738 fet_endchar;
2739
2740
2741 %%%%%%  Walker ti head
2742 %       Triangular arrowhead
2743 %       Rotates for all but whole notes
2744 %
2745 def draw_Walker_ti_head (expr width_factor, thickness_factor) =
2746         set_char_box (0, width_factor * solfa_base_notewidth#,
2747                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
2748
2749         save offset;
2750         offset := 2 * thickness_factor - 1;
2751
2752         save pen_radius;
2753         pen_radius := min (solfa_pen_radius,
2754                            .3 * (h + d) / (1 + offset));
2755
2756         pickup pencircle scaled (2 * pen_radius);
2757
2758         lft x1 = 0;
2759         y1 = .5 [y2, y3];
2760
2761         rt x2 = w;
2762         top y2 = h;
2763
2764         x3 = x2;
2765         bot y3 = -d;
2766
2767
2768         labels (range 1 thru 4);
2769
2770         save nw_dist, sw_dist, ne, se;
2771         pair nw_dist, sw_dist, ne, se;
2772
2773         ne = unitvector (z2 - z1);
2774         se = unitvector (z3 - z1);
2775
2776         nw_dist = (ne rotated 90) * pen_radius ;
2777         sw_dist = (se rotated -90) * pen_radius;
2778
2779
2780         save path_a, path_b, path_c;
2781         path path_a, path_b, path_c;
2782         path_a := z2 - nw_dist * offset
2783                   -- z1 - nw_dist * offset;
2784         path_b := z3 - sw_dist * offset
2785                   -- z1 - sw_dist * offset;
2786         path_c := z2 + left * pen_radius
2787                   -- z3 + left * pen_radius;
2788
2789         z4 = path_a intersectionpoint path_b;
2790         z5 = path_a intersectionpoint path_c;
2791         z6 = path_b intersectionpoint path_c;
2792
2793         save p_up_in, p_down_in, p_up_out, p_down_out;
2794         path p_up_in, p_down_in, p_up_out, p_down_out;
2795
2796         p_down_in := z4
2797                      -- z5
2798                      -- z6
2799                      -- cycle;
2800
2801         p_down_out := lft z1{up}
2802                       .. (z1 + nw_dist){ne}
2803                       -- (z2 + nw_dist){ne}
2804                       .. top z2{right}
2805                       .. rt z2 {down}
2806                       -- rt z3 {down}
2807                       .. bot z3 {left}
2808                       .. (z3 + sw_dist){- se}
2809                       .. (z1 + sw_dist){- se}
2810                       .. cycle;
2811
2812         p_up_in := p_down_in rotated 180 shifted (w, 0);
2813         p_up_out := p_down_out rotated 180 shifted (w, 0);
2814 enddef;
2815
2816
2817 save walker_ti_weight;
2818 walker_ti_weight := 1.4;
2819
2820 fet_beginchar ("Whole Walker tihead", "s0tiWalker");
2821         draw_Walker_ti_head (funk_notehead_width, walker_ti_weight);
2822         fill p_down_out;
2823         unfill p_down_in;
2824 fet_endchar;
2825
2826
2827 fet_beginchar ("Half up Walker tihead", "u1tiWalker");
2828         draw_Walker_ti_head (funk_notehead_width, walker_ti_weight);
2829         fill p_up_out;
2830         unfill p_up_in;
2831 fet_endchar;
2832
2833
2834 fet_beginchar ("Half down Walker tihead", "d1tiWalker");
2835         draw_Walker_ti_head (funk_notehead_width, walker_ti_weight);
2836         fill p_down_out;
2837         unfill p_down_in;
2838 fet_endchar;
2839
2840
2841 fet_beginchar ("Quarter up Walker tihead", "u2tiWalker");
2842         draw_Walker_ti_head (funk_notehead_width, walker_ti_weight);
2843         fill p_up_out;
2844 fet_endchar;
2845
2846
2847 fet_beginchar ("Quarter down Walker tihead", "d2tiWalker");
2848         draw_Walker_ti_head (funk_notehead_width, walker_ti_weight);
2849         fill p_down_out;
2850 fet_endchar;
2851
2852 fet_endgroup ("noteheads");
2853
2854
2855 %
2856 % we derive black_notehead_width# from the quarter head,
2857 % so we have to define black_notehead_width (pixel qty)
2858 % after the black_notehead_width# itself.
2859 %
2860 % Let's keep it outside the group as well.
2861 %
2862
2863 define_pixels (black_notehead_width);