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