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