Fixes Issue 1504, allowing feather beam line breaking.
[lilypond/patrick.git] / mf / feta-accidentals.mf
blobfeac34f9ed68e0b6288439e99548db04a3a40d07
1 % Feta (not the Font-En-Tja) music font --  Accidentals
2 % This file is part of LilyPond, the GNU music typesetter.
4 % Copyright (C) 1997--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 % LilyPond is free software: you can redistribute it and/or modify
8 % it under the terms of the GNU General Public License as published by
9 % the Free Software Foundation, either version 3 of the License, or
10 % (at your option) any later version.
12 % LilyPond is distributed in the hope that it will be useful,
13 % but WITHOUT ANY WARRANTY; without even the implied warranty of
14 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 % GNU General Public License for more details.
17 % You should have received a copy of the GNU General Public License
18 % along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
22 % also show in other configuration wrt staff lines.
24 def draw_shifted_too =
25 if test > 0:
26         fet_beginchar ("shifted too", "");
27                 set_char_box (0, 0, 0, 0);
28                 currentpicture := remember_pic;
30                 draw_staff (-2, 2, 0.5);
31         fet_endchar;
32 fi;
33 enddef;
37 % Accidentals from various sources, notably
39 %   Baerenreiter edition of Schuberts `Auf dem Strom' (sharp, natural)
40 %   F Hofmeister edition of Muellers `Etueden fuer Horn' (double sharp, flat)
45 % Naming for accidentals (including microtonal variants):
47 %   SHARPBASE[.SLASHES.STEMS]
48 %   FLATBASE[.MODIFIER]
50 % Examples:
52 %   sharp.slashslash.stem
53 %   mirroredflat.flat
58 fet_begingroup ("accidentals");
61 % Draw an arrow
63 % * `stemslant' gives the direction of the stem's left boundary
64 %   (needed for brushed stems, equals "up" for straight stems)
65 % * `extend' is used to make the stem longer or shorter (if negative);
66 %   different kinds of accidentals need different values here
68 def draw_arrow (expr attach, stemwidth, stemslant, extend, pointingdown) =
69 begingroup;
70         save htip;  % tip height
71         save wwing; % wing `radius'
72         save angle_wing_bot, angle_wing_top, angle_tip;
73         save upshift;
74         clearxy;
76         wwing := 0.26 stemwidth;
77         htip := staff_space * 0.85 + stafflinethickness - wwing;
79         % `flip' is used to reflect the arrow vertically
80         % if arrow points downward
81         transform flip;
82         if pointingdown:
83                 flip = identity reflectedabout (origin, right);
84         else:
85                 flip = identity;
86         fi;
88         z1 = attach shifted (-stemwidth / 2, 0);
89         upshift := max (0, wwing + 0.1 staff_space + extend);
90         z2 = z1 shifted (((unitvector stemslant)
91                           scaled upshift) transformed flip);
93         z7 = attach shifted ((stemwidth/2),0);
94         z6 = z7 shifted (((unitvector (-xpart stemslant, ypart stemslant))
95                           scaled upshift) transformed flip);
96         z2 - z3 = ( 0.38 staff_space, 0.05 htip) transformed flip;
97         z6 - z5 = (-0.38 staff_space, 0.05 htip) transformed flip;
99         z4 = attach shifted ((-0.2 stemwidth, upshift + htip)
100                              transformed flip);
101         z4'= attach shifted (( 0.2 stemwidth, upshift + htip)
102                              transformed flip);
104         % `angle_wing_bot' is the angle at which the arc
105         % from z2 to z3a enters z3a
106         % `angle_wing_top' is the angle at which the arc
107         % from z3b to z4 leaves z3b
108         % `angle_tip' is the angle at which the arc
109         % from z4 to z4' leaves z4
110         angle_wing_bot = 30;
111         angle_wing_top = 55;
112         angle_tip = 68;
114         z3a = z3 shifted ((((dir angle_wing_bot) rotated -90)
115                            scaled wwing) transformed flip);
116         z3b = z3 shifted ((((dir angle_wing_top) rotated 90)
117                            scaled wwing) transformed flip);
119         z5a = z5 shifted ((((dir (180 - angle_wing_bot)) rotated 90)
120                            scaled wwing) transformed flip);
121         z5b = z5 shifted ((((dir (180 - angle_wing_top)) rotated -90)
122                            scaled wwing) transformed flip);
124         % Draw the arrow
125         pickup pencircle scaled 1;
126         fill z1
127              -- z2{stemslant transformed flip}
128              .. {(-dir angle_wing_bot) transformed flip}z3a
129              .. z3b{(dir angle_wing_top) transformed flip}
130              .. z4{(dir angle_tip) transformed flip}
131              .. z4'{(dir (-angle_tip)) transformed flip}
132              .. {(dir (-angle_wing_top)) transformed flip}z5b
133              .. z5a{(-dir (-angle_wing_bot)) transformed flip}
134              .. z6{((-stemslant) reflectedabout (origin, up)) transformed flip}
135              -- z7
136              -- cycle;
138         labels (range 0 thru 7, 4', 3a, 3b, 5a, 5b);
139 endgroup;
140 enddef;
142 save remember_pic;
143 picture remember_pic;
145 save sharp_beamheight;
146 sharp_beamheight# := 0.3 staff_space# + stafflinethickness#;
149 % The beams of most sharps have horizontal endings (as if drawn with
150 % a square pen).  [Wanske] does not mention this, so we'll just ignore
151 % this fact.
154 def draw_meta_sharp (expr width, offset) =
155         save beamwidth, beamslope;
156         save ne, nw_dist;
157         pair ne, nw_dist;
159         beamwidth := width;
161         define_whole_vertical_blacker_pixels (sharp_beamheight);
163         clearxy;
165         beamslope = sharp_beamheight / beamwidth;
167         pickup pencircle scaled 2 blot_diameter;
169         rt x2 - lft x1 = beamwidth;
170         z2 = z1 + whatever * (beamwidth, sharp_beamheight);
171         .5 [z1, z3] = (.5 w, offset);
172         x3 = x2;
173         top y2 - bot y3 = sharp_beamheight;
174         x4 = x1;
175         top y1 - bot y4 = sharp_beamheight;
177         ne = unitvector (z2 - z1);
178         nw_dist = (ne rotated 90) * blot_diameter;
180         fill lft z1{up}
181              ... (z1 + nw_dist){ne}
182              -- (z2 + nw_dist){ne}
183              ... rt z2{down}
184              -- rt z3{down}
185              ... (z3 - nw_dist){-ne}
186              -- (z4 - nw_dist){-ne}
187              ... lft z4{up}
188              -- cycle;
190         labels (1, 2, 3, 4);
191 enddef;
194 def draw_sharp(expr arrowup, arrowdown) =
195         save stem, stemx, stemwidth;
196         save outer_space, interbeam;
197         save stemlength, extendleft, extendright, height, depth;
199         stemwidth# := stafflinethickness# + .05 staff_space#;
200         define_whole_blacker_pixels (stemwidth);
202         interbeam := 1.05 staff_space_rounded;
204         stemlength# := 1.5 staff_space#;
205         define_pixels (stemlength);
207         height# = stemlength#;
208         depth# = stemlength#;
209         extendright# = 0;
210         extendleft# = 0;
211         if arrowup:
212                 height# := height# + 1.2 staff_space#;
213                 extendright# := extendright# + 1.5 stafflinethickness#;
214         fi;
215         if arrowdown:
216                 depth# := depth# + 1.2 staff_space#;
217                 extendleft# := extendleft# + 1.5 stafflinethickness#;
218         fi;
219         define_pixels (extendleft, extendright);
220         set_char_box (extendleft#, 1.1 staff_space#, depth#, height#);
222         stem := 7 / 16 * w;
223         stemx := hround stem;
224         outer_space := hround ((w - stemx - stemwidth) / 2);
226         w := 2 outer_space + stemx + stemwidth;
227         d := d - feta_space_shift;
229         draw_meta_sharp (w, -.5 interbeam);
230         draw_meta_sharp (w, -.5 interbeam + vround interbeam);
232         % expand the charbox so that it encloses the whole arrow;
233         % this must not happen earlier because some commands above
234         % still rely on the old width
235         w := w + extendright;
237         pickup pencircle scaled stemwidth;
239         lft x5 = lft x6 = outer_space;
240         lft x7 = lft x8 = outer_space + stemx;
241         bot y5 = -stemlength;
242         top y6 = vround (1.5 staff_space - stem * beamslope);
243         bot y7 = -top y6 + feta_space_shift;
244         top y8 = stemlength;
246         labels (5, 6, 7, 8);
248         draw_gridline (z5, z6, stemwidth);
249         draw_gridline (z7, z8, stemwidth);
251         if arrowup:
252                 draw_arrow (z8, stemwidth, up,
253                             stafflinethickness / 2 + stemwidth / 2, false);
254         fi;
255         if arrowdown:
256                 draw_arrow (z5, stemwidth, up,
257                             stafflinethickness / 2 + stemwidth / 2, true);
258         fi;
260         remember_pic := currentpicture;
262         draw_staff (-2, 2, 0);
263 enddef;
266 fet_beginchar ("Sharp", "sharp");
267         draw_sharp (false, false);
268 fet_endchar;
271 draw_shifted_too;
274 fet_beginchar ("Arrowed Sharp (arrow up)", "sharp.arrowup");
275         draw_sharp (true, false);
276 fet_endchar;
279 draw_shifted_too;
282 fet_beginchar ("Arrowed Sharp (arrow down)", "sharp.arrowdown");
283         draw_sharp (false, true);
284 fet_endchar;
287 draw_shifted_too;
290 fet_beginchar ("Arrowed Sharp (arrows up and down)", "sharp.arrowboth");
291         draw_sharp (true, true);
292 fet_endchar;
295 draw_shifted_too;
298 fet_beginchar ("1/2 Sharp", "sharp.slashslash.stem");
299         save stem, stemwidth;
300         save outer_space, interbeam;
302         stemwidth# := stafflinethickness# + .05 staff_space#;
303         define_whole_blacker_pixels (stemwidth);
305         interbeam := 1.05 staff_space_rounded;
307         set_char_box (0, 0.7 staff_space#,
308                       1.5 staff_space#, 1.5 staff_space#);
310         stem := 7 / 16 * w;
311         outer_space := hround ((w - stemwidth) / 2);
313         w := 2 outer_space + stemwidth;
314         d := d - feta_space_shift;
316         draw_meta_sharp (w, -.5 interbeam);
317         draw_meta_sharp (w, -.5 interbeam + vround interbeam);
319         pickup pencircle scaled stemwidth;
321         lft x5 = lft x6 = outer_space;
322         top y6 = vround (1.5 staff_space - .5 stem);
323         bot y5 = -top y6 + feta_space_shift;
325         labels (5, 6);
327         draw_gridline (z5, z6, stemwidth);
329         remember_pic := currentpicture;
331         draw_staff (-2, 2, 0);
332 fet_endchar;
335 draw_shifted_too;
338 fet_beginchar ("Sharp (3 beams)", "sharp.slashslashslash.stemstem");
339         save stem, stemx, stemwidth;
340         save outer_space, interbeam;
341         save sharp_beamheight;
343         sharp_beamheight# := 0.22 staff_space# + stafflinethickness#;
345         stemwidth# := stafflinethickness# + .05 staff_space#;
346         define_whole_blacker_pixels (stemwidth);
348         interbeam := 1.2 staff_space_rounded;
350         set_char_box (0, 1.1 staff_space#,
351                       1.5 staff_space#, 1.5 staff_space#);
353         stem := 7 / 16 * w;
354         stemx := hround stem;
355         outer_space := hround ((w - stemx - stemwidth) / 2);
357         w := 2 outer_space + stemx + stemwidth;
358         d := d - feta_space_shift;
360         draw_meta_sharp (.88 w, -.5 interbeam);
361         draw_meta_sharp (.88 w, -.5 interbeam + vround interbeam);
362         sharp_beamheight# := 1/.88 sharp_beamheight#;
363         draw_meta_sharp (w, 0);
365         pickup pencircle scaled stemwidth;
367         lft x5 = lft x6 = outer_space;
368         lft x7 = lft x8 = outer_space + stemx;
369         bot y5 = -d;
370         top y6 = vround (1.5 staff_space - stem * beamslope);
371         bot y7 = -top y6 + feta_space_shift;
372         top y8 = h;
374         labels (5, 6, 7, 8);
376         draw_gridline (z5, z6, stemwidth);
377         draw_gridline (z7, z8, stemwidth);
379         remember_pic := currentpicture;
381         draw_staff (-2, 2, 0);
382 fet_endchar;
385 draw_shifted_too;
388 fet_beginchar ("1/2 Sharp (3 beams)", "sharp.slashslashslash.stem");
389         save stem, stemx, stemwidth;
390         save outer_space, interbeam;
391         save sharp_beamheight;
393         sharp_beamheight# := 0.22 staff_space# + stafflinethickness#;
395         stemwidth# := stafflinethickness# + .05 staff_space#;
396         define_whole_blacker_pixels (stemwidth);
398         interbeam := 1.2 staff_space_rounded;
400         set_char_box (0, 0.95 staff_space#,
401                       1.3 staff_space#, 1.3 staff_space#);
403         stem := 7 / 16 * w;
404         outer_space := hround ((w - stemwidth) / 2);
406         w := 2 outer_space + stemwidth;
407         d := d - feta_space_shift;
409         draw_meta_sharp (.8 w, -.5 interbeam);
410         draw_meta_sharp (.8 w, -.5 interbeam + vround interbeam);
411         sharp_beamheight# := 1/.8 sharp_beamheight#;
412         draw_meta_sharp (w, 0);
414         pickup pencircle scaled stemwidth;
416         lft x5 = lft x6 = outer_space;
417         top y6 = vround (1.5 staff_space - .5 stem);
418         bot y5 = -top y6 + feta_space_shift;
419         labels (5, 6);
421         draw_gridline (z5, z6, stemwidth);
423         remember_pic := currentpicture;
425         draw_staff (-2, 2, 0);
426 fet_endchar;
429 draw_shifted_too;
432 fet_beginchar ("3/4 Sharp", "sharp.slashslash.stemstemstem");
433         save stem, stemx, stemwidth;
434         save outer_space, interbeam;
436         stemwidth# := stafflinethickness# + .05 staff_space#;
437         define_whole_blacker_pixels (stemwidth);
439         interbeam := 1.05 staff_space_rounded;
441         set_char_box (0, 1.6 staff_space#,
442                       1.5 staff_space#, 1.5 staff_space#);
444         stem := 9 / 32 * w;
445         stemx := hround stem;
446         outer_space := hround ((w - 2 stemx - stemwidth) / 2);
448         w := 2 outer_space + 2 stemx + stemwidth;
449         d := d - feta_space_shift;
451         draw_meta_sharp (w, -.5 interbeam);
452         draw_meta_sharp (w, -.5 interbeam + vround interbeam);
454         pickup pencircle scaled stemwidth;
456         lft x5 = lft x6 = outer_space;
457         lft x7 = lft x8 = outer_space + stemx;
458         lft x9 = lft x10 = outer_space + 2 stemx;
459         bot y5 = -d;
460         top y6 = vround (1.5 staff_space - 2 stem * beamslope);
461         bot y9 = -top y6 + feta_space_shift;
462         top y10 = h;
463         y7 = .5 [y5, y9];
464         y8 = .5 [y6, y10];
466         labels (5, 6, 7, 8, 9, 10);
468         draw_gridline (z5, z6, stemwidth);
469         draw_gridline (z7, z8, stemwidth);
470         draw_gridline (z9, z10, stemwidth);
472         remember_pic := currentpicture;
474         draw_staff (-2, 2, 0);
475 fet_endchar;
478 draw_shifted_too;
482 % The stems of the natural are brushed (at least, in Barenreiter SCS)
485 def draw_natural (expr arrowup, arrowdown) =
486         save stemwidth, top_stem_thick;
487         save ne, pat_top, pat_bottom;
488         save depth, height, extendleft, extendright, stemlength;
489         save brush_scale_up, brush_scale_down;
490         pair ne;
491         path pat_top, pat_bottom;
493         top_stem_thick# = stafflinethickness# + .10 staff_space#;
494         stemwidth# = 0.09 staff_space# + .5 stafflinethickness#;
495         define_whole_blacker_pixels (top_stem_thick, stemwidth);
497         stemlength# = 1.5 staff_space#;
498         define_pixels (stemlength);
500         height# = stemlength#;
501         depth# = stemlength#;
502         extendleft# = 0;
503         extendright# = 0;
504         if arrowup:
505                 extendleft# := 3 stafflinethickness#;
506                 height# := height# + 1.2 staff_space#;
507         fi;
508         if arrowdown:
509                 extendright# := 3.15 stafflinethickness#;
510                 depth# := depth# + 1.2 staff_space#;
511         fi;
512         define_pixels (extendright);
514         set_char_box (extendleft#, 2/3 staff_space#, depth#, height#);
516         d := d - feta_space_shift;
518         pickup pencircle scaled stemwidth;
520         brush_scale_up := 1.0;
521         brush_scale_down := 1.0;
522         % to look nice, arrowed stems must be less brushed
523         if arrowup:
524                 brush_scale_up := 0.85;
525         fi;
526         if arrowdown:
527                 brush_scale_down := 0.85;
528         fi;
530         penpos1 (top_stem_thick, 0);
531         penpos3 (top_stem_thick, 0);
532         penpos2 (stemwidth, 0);
533         penpos4 (stemwidth, 0);
534         % z1' and z3' are needed for the arrowed accidentals
535         penpos1' (top_stem_thick * brush_scale_up, 0);
536         penpos3' (top_stem_thick * brush_scale_down, 0);
538         x2r = w;
539         x4l = 0;
540         x3 = x3' = x2;
541         x1 = x1' = x4;
543         y1 = y1' = stemlength;
544         y3 = y3' = -stemlength;
545         top y2 = vround (staff_space - 3/2 stafflinethickness);
546         y4 = -y2 + feta_space_shift;
548         pat_bottom := z4r{z4r - z1r}
549                       .. bot z4
550                       .. z4l{z1l - z4l};
551         fill simple_serif (z1'l, z1'r, -30)
552              -- pat_bottom
553              -- cycle;
555         pat_top := z2r{z2r - z3r}
556                    .. top z2
557                    .. z2l{z3l - z2l};
558         fill simple_serif (z3'l, z3'r, 30)
559              -- pat_top
560              -- cycle;
562         ne = (x2 - x4, stafflinethickness);
564         z11' = z3l + whatever * (z2l - z3l);
565         y11' = vround (.5 (staff_space - stafflinethickness));
566         z11 = z11' + whatever * ne;
567         x11 = x12;
568         z12 = directionpoint -ne of pat_top;
569         z13 = z12 + whatever * ne;
570         x13 = x1;
571         z14 = z11 + whatever * ne;
572         x14 = x1;
574         z21' = z4r + whatever * (z1r - z4r);
575         y21' = -y11' + feta_space_shift;
576         z21 = z21' + whatever * ne;
577         x21 = x22;
578         z22 = directionpoint -ne of pat_bottom;
579         z23 = z22 + whatever * ne;
580         x23 = x3;
581         z24 = z21 + whatever * ne;
582         x24 = x3;
584         fill z11
585              -- z12
586              -- z13
587              -- z14
588              -- cycle;
589         fill z21
590              -- z22
591              -- z23
592              -- z24
593              -- cycle;
595         penlabels (1, 1', 2, 3, 3', 4);
596         labels (11, 11', 12, 13, 14, 21, 21', 22, 23, 24);
598         if arrowup:
599                 draw_arrow (z1, top_stem_thick * brush_scale_up,
600                             z1'l - z4l, stafflinethickness / 2, false);
601         fi;
602         if arrowdown:
603                 draw_arrow (z3, top_stem_thick * brush_scale_down,
604                             z2r - z3'r, stafflinethickness / 2, true);
605                 w := w + extendright;
606         fi;
608         remember_pic := currentpicture;
610         draw_staff (-2, 2, 0);
611 enddef;
614 fet_beginchar ("Natural", "natural");
615         draw_natural (false, false);
616 fet_endchar;
619 draw_shifted_too;
622 fet_beginchar ("Arrowed Natural (arrow up)", "natural.arrowup");
623         draw_natural (true, false);
624 fet_endchar;
627 draw_shifted_too;
630 fet_beginchar ("Arrowed Natural (arrow down)", "natural.arrowdown");
631         draw_natural (false, true);
632 fet_endchar;
635 draw_shifted_too;
638 fet_beginchar ("Arrowed Natural (arrows up and down)", "natural.arrowboth");
639         draw_natural (true, true);
640 fet_endchar;
643 draw_shifted_too;
647 % Dedicated to my mom.    (3/10/97)
649 % Mamma, ik hou van je; kom je alsjeblieft terug?
650 %    -- HW
653 % TODO: remove crook_fatness
654 % TODO: document, simplify!
657 def draw_meta_flat (expr xcenter, w, crook_fatness, arrowup, arrowdown) =
658         save crook_thinness;
659         save bottom_overshoot, bot_crook_dir;
660         save top_stem_thick, top_stem_thick_orig;
661         save bottom_stem_thick, hair, smaller_hole;
662         save top_crook_thinness;
663         save zwiep;
664         save center;
665         pair center, bot_crook_dir;
666         save clearing, clearing_orig;
668         clearxy;
670         % the stem shouldn't reach the top staff line.
671         %% TODO: should take from height.
672         %
673         % TODO: parameterize this
674         %
675         if w >= 0.75 staff_space:
676                 smaller_hole = 0.35 stafflinethickness;
677         else:
678                 smaller_hole = 0;
679         fi;
680         crook_thinness = .7 stafflinethickness + .06 staff_space;
681         top_crook_thinness = 1 stafflinethickness + .065 staff_space;
682         clearing = 1.7 stafflinethickness;
683         clearing_orig = clearing;
684         if arrowup:
685                 clearing := 0.5 staff_space;
686         fi;
687         bottom_overshoot = stafflinethickness;
689         bottom_stem_thick# = 0.06 staff_space# + 0.6 stafflinethickness#;
690         top_stem_thick# = 0.1 staff_space# + 1.2 stafflinethickness#;
691         top_stem_thick_orig# = top_stem_thick#;
692         if arrowup:
693                 % to look nice, arrowed stems should be less brushed
694                 top_stem_thick# := top_stem_thick# * 0.8;
695         fi;
696         define_whole_blacker_pixels (bottom_stem_thick, top_stem_thick,
697                                      top_stem_thick_orig);
699         if odd (top_stem_thick - bottom_stem_thick):
700                 top_stem_thick := top_stem_thick - 1;
701         fi;
702         if odd (top_stem_thick_orig - bottom_stem_thick):
703                 top_stem_thick_orig := top_stem_thick_orig - 1;
704         fi;
706         center = (xcenter, 0);
708         x1l = hround (xcenter - .5 top_stem_thick);
709         y1 = vround (2 staff_space - clearing);
710         x2l = hround (xcenter - .5 bottom_stem_thick);
711         y2 = -.5 staff_space - .5 stafflinethickness;
712         % z16 and the `*_orig' variables are needed for arrowed accidentals
713         % because their inner part should be unchanged from plain ones but
714         % the points z3l, z3r, and z10 depend on values that are different
715         % for arrowed accidentals
716         x16l = hround (xcenter -.5 top_stem_thick_orig);
717         y16 = vround (2 staff_space - clearing_orig);
719         penpos1 (top_stem_thick, 0);
720         penpos16 (top_stem_thick_orig, 0);
721         penpos2 (bottom_stem_thick, 0);
723         y3l = vfloor ((staff_space - stafflinethickness) / 2);
724         z3l = whatever [z2r, z1r];
725         z3r = .3 [z2r,
726                   (z16r shifted (0, clearing_orig - 1.7 stafflinethickness))]
727               + (smaller_hole, 0);
728         x3r := hceiling x3r;
730         % we insert z3l to get better conversion with mf2pt1
731         fill simple_serif (z1r, z1l, 30)
732              -- z2l
733              -- z2r
734              -- z3l
735              -- cycle;
737         z10 = whatever [z2r, z16r] + (smaller_hole, 0);
738         y10 = -1/10 staff_space;
739         x10 := hceiling x10;
741         x11 = xcenter + bottom_overshoot / 3;
742         y11 = -vround (.5 (staff_space + stafflinethickness)
743                        + bottom_overshoot);
745         x2a = 0.2[x2r, x7];
746         y2a = 1.5[y2, y11];
748         penpos4 (whatever, 53);
750         y4l - y4r = top_crook_thinness;
751         y5r = .15 staff_space;
752         x5l = hround (w + xcenter);
753         y4 = staff_space / 2;
754         x4r = .45 [x5r, x3r];
755         y4l := vround y4l;
757         penpos5 (crook_fatness, -175);
759         bot_crook_dir = unitvector ((x5l, 0) - z11);
760         z8 = z11 + whatever * bot_crook_dir;
761         y8 = -staff_space / 2;
763         z7 = z8
764              + whatever * bot_crook_dir
765              + crook_thinness * (bot_crook_dir rotated 90);
766         x7 = .1 [x3r, x8];
768         unfill z3r{z3r - z10}
769                .. z4r{right}
770                .. z5r{down}
771                .. z7{-bot_crook_dir}
772                & z7
773                .. z10{z3r - z10}
774                -- cycle;
776         if arrowdown:
777                 fill z2l{down}
778                      .. z2a{up}
779                      .. z8{bot_crook_dir}
780                      .. z5l{up}
781                      .. z4l{left}
782                      .. z3l
783                      -- cycle;
784         else:
785                 fill z2l{down}
786                      .. z11{right}
787                      .. z8{bot_crook_dir}
788                      .. z5l{up}
789                      .. z4l{left}
790                      .. z3l
791                      -- cycle;
792         fi;
794         if arrowup:
795                 draw_arrow (z1, top_stem_thick, z1l - z2l,
796                             0.5 stafflinethickness, false);
797         fi;
798         if arrowdown:
799                 draw_arrow ((0.5 [x2l, x2a], y2), x2a - x2l, up,
800                             staff_space / 2, true);
801         fi;
802 enddef;
805 def draw_arrowed_meta_flat (expr xcenter, width, crook_fatness,
806                                  arrowup, arrowdown) =
807         save depth, height, extendleft;
809         depth# = 0.6 staff_space#;
810         height# = 1.9 staff_space#;
811         extendleft# := 1.2 stafflinethickness#;
812         if arrowup:
813                 extendleft# := 3.45 stafflinethickness#;
814                 height# := height# + 0.8 staff_space#;
815         fi;
816         if arrowdown:
817                 extendleft# := 3.45 stafflinethickness#;
818                 depth# := depth# + 1.6 staff_space#;
819         fi;
821         set_char_box (extendleft#, width, depth#, height#);
822         draw_meta_flat(xcenter, w, crook_fatness, arrowup, arrowdown);
823 enddef;
826 % unfortunately, 600dpi is not enough to show the brush of the stem.
829 fet_beginchar ("Flat", "flat");
830         draw_arrowed_meta_flat (0, 0.8 staff_space#, 0.31 staff_space,
831                                 false, false);
832         penlabels (range 0 thru 11);
834         remember_pic := currentpicture;
836         draw_staff (-2, 2, 0);
837 fet_endchar;
840 draw_shifted_too;
843 fet_beginchar ("Arrowed Flat (arrow up)", "flat.arrowup");
844         draw_arrowed_meta_flat (0, 0.8 staff_space#, 0.31 staff_space,
845                                 true, false);
846         penlabels (range 0 thru 23);
848         remember_pic := currentpicture;
850         draw_staff (-2, 2, 0);
851 fet_endchar;
854 draw_shifted_too;
857 fet_beginchar ("Arrowed Flat (arrow down)", "flat.arrowdown");
858         draw_arrowed_meta_flat (0, 0.8 staff_space#, 0.31 staff_space,
859                                 false, true);
860         penlabels (range 0 thru 23);
862         remember_pic := currentpicture;
864         draw_staff (-2, 2, 0);
865 fet_endchar;
868 draw_shifted_too;
871 fet_beginchar ("Arrowed Flat (arrow up and down)", "flat.arrowboth");
872         draw_arrowed_meta_flat (0, 0.8 staff_space#, 0.31 staff_space,
873                                 true, true);
874         penlabels (range 0 thru 23);
876         remember_pic := currentpicture;
878         draw_staff (-2, 2, 0);
879 fet_endchar;
882 draw_shifted_too;
885 fet_beginchar ("Flat (slashed)", "flat.slash");
886         set_char_box (.4 staff_space#, .8 staff_space#,
887                       0.6 staff_space#, 1.9 staff_space#);
889         draw_meta_flat (0, w, 0.31 staff_space, false, false);
891         clearxy;
893         save slope, slash_width;
894         slope = 0.5;
895         slash_width = w;
897         z11 = (0, h / 2);
898         z12 = z11 - (slash_width, slash_width * slope) / 2;
899         z13 = z11 + (slash_width, slash_width * slope) / 2;
900         penpos12 (1.5 stafflinethickness, angle (z13 - z12) - 90);
901         penpos13 (1.5 stafflinethickness, angle (z13 - z12) - 90);
903         z14 = z12 - .75 stafflinethickness * unitvector (z13 - z12);
904         z15 = z13 + .75 stafflinethickness * unitvector (z13 - z12);
906         fill z13r
907              .. z15
908              .. z13l
909              -- z12l
910              .. z14
911              .. z12r
912              -- z13r
913              .. cycle;
915         penlabels (12, 13);
916         labels (14, 15);
918         remember_pic := currentpicture;
920         draw_staff (-2, 2, 0);
921 fet_endchar;
924 fet_beginchar ("Flat (slashed twice)", "flat.slashslash");
925         set_char_box (.4 staff_space#, .8 staff_space#,
926                       0.6 staff_space#, 1.9 staff_space#);
928         draw_meta_flat (0, w, 0.31 staff_space, false, false);
930         clearxy;
932         save slope, slash_width;
933         slope = 0.5;
934         slash_width = w;
936         z11 = (0, 5/12 h);
937         z12 = z11 - (slash_width, slash_width * slope) / 2;
938         z13 = z11 + (slash_width, slash_width * slope) / 2;
939         penpos12 (1.5 stafflinethickness, angle (z13 - z12) - 90);
940         penpos13 (1.5 stafflinethickness, angle (z13 - z12) - 90);
942         z14 = z12 - .75 stafflinethickness * unitvector (z13 - z12);
943         z15 = z13 + .75 stafflinethickness * unitvector (z13 - z12);
945         fill z13r
946              .. z15
947              .. z13l
948              -- z12l
949              .. z14
950              .. z12r
951              -- z13r
952              .. cycle;
954         penlabels (12, 13);
955         labels (14, 15);
957         z21 = (0, 2/3 h);
958         z22 = z21 - (slash_width, slash_width * slope) / 2;
959         z23 = z21 + (slash_width, slash_width * slope) / 2;
960         penpos22 (1.5 stafflinethickness, angle (z23 - z22) - 90);
961         penpos23 (1.5 stafflinethickness, angle (z23 - z22) - 90);
963         z24 = z22 - .75 stafflinethickness * unitvector (z23 - z22);
964         z25 = z23 + .75 stafflinethickness * unitvector (z23 - z22);
966         fill z23r
967              .. z25
968              .. z23l
969              -- z22l
970              .. z24
971              .. z22r
972              -- z23r
973              .. cycle;
975         penlabels (22, 23);
976         labels (24, 25);
978         remember_pic := currentpicture;
980         draw_staff (-2, 2, 0);
981 fet_endchar;
984 fet_beginchar ("Flatflat (mirrored)", "mirroredflat.flat");
985         set_char_box (0, 1.6 staff_space#,
986                       0.6 staff_space#, 1.9 staff_space#);
988         % This is a modified version of `draw_meta_flat'.
990         save crook_thinness, crook_fatness;
991         save bottom_overshoot, bot_crook_dir;
992         save top_stem_thick, bottom_stem_thick, hair, smaller_hole;
993         save top_crook_thinness;
994         save zwiep;
995         save center;
996         pair center, bot_crook_dir;
997         save clearing, wid;
998         save pat;
999         path pat;
1001         clearxy;
1003         wid = w / 2;
1005         % the stem shouldn't reach the top staff line.
1006         %% TODO: should take from height.
1007         %
1008         % TODO: parameterize this
1009         %
1010         if wid >= 0.75 staff_space:
1011                 smaller_hole = 0.35 stafflinethickness;
1012         else:
1013                 smaller_hole = 0;
1014         fi;
1015         clearing = 1.7 stafflinethickness;
1016         crook_thinness = .7 stafflinethickness + .06 staff_space;
1017         crook_fatness = 0.31 staff_space;
1018         top_crook_thinness = 1 stafflinethickness + .065 staff_space;
1019         bottom_overshoot = stafflinethickness;
1021         bottom_stem_thick# = 0.06 staff_space# + 0.6 stafflinethickness#;
1022         top_stem_thick# = 0.1 staff_space# + 1.2 stafflinethickness#;
1023         define_whole_blacker_pixels (bottom_stem_thick, top_stem_thick);
1025         if odd (top_stem_thick - bottom_stem_thick):
1026                 top_stem_thick := top_stem_thick - 1;
1027         fi;
1029         center = (0, 0);
1031         x1l = hround (-.5 top_stem_thick);
1032         y1 = vround (2 staff_space - clearing);
1033         x2l = hround (-.5 bottom_stem_thick);
1034         y2 = -.5 staff_space - .5 stafflinethickness;
1036         penpos1 (top_stem_thick, 0);
1037         penpos2 (bottom_stem_thick, 0);
1039         y3l = vfloor ((staff_space - stafflinethickness) / 2);
1040         z3l = whatever [z2r, z1r];
1041         z3r = .3 [z2r, z1r] + (smaller_hole, 0);
1042         x3r := hceiling x3r;
1044         z10 = whatever [z2r, z1r] + (smaller_hole, 0);
1045         y10 = -1/10 staff_space;
1046         x10 := hceiling x10;
1048         x11 = bottom_overshoot / 3;
1049         y11 = -vround (.5 (staff_space + stafflinethickness)
1050                        + bottom_overshoot);
1052         penpos4 (whatever, 53);
1054         y4l - y4r = top_crook_thinness;
1055         y5r = .15 staff_space;
1056         x5l = hround (wid);
1057         y4 = staff_space / 2;
1058         x4r = .45 [x5r, x3r];
1059         y4l := vround y4l;
1061         penpos5 (crook_fatness, -175);
1063         bot_crook_dir = unitvector ((x5l, 0) - z11);
1064         z8 = z11 + whatever * bot_crook_dir;
1065         y8 = -staff_space / 2;
1067         z7 = z8
1068              + whatever * bot_crook_dir
1069              + crook_thinness * (bot_crook_dir rotated 90);
1070         x7 = .1 [x3r, x8];
1072         pat := z3r{z3r - z10}
1073                .. z4r{right}
1074                .. z5r{down}
1075                .. z7{-bot_crook_dir}
1076                & z7
1077                .. z10{z3r - z10}
1078                -- cycle;
1079         unfill pat;
1080         unfill pat xscaled -1;
1082         pat := z11{right}
1083                .. z8{bot_crook_dir}
1084                .. z5l{up}
1085                .. z4l{left}
1086                .. z3l;
1087         fill pat
1088              -- simple_serif (z1r, z1l, 30)
1089              -- reverse pat xscaled -1 shifted (-feta_eps, 0)
1090              -- cycle;
1092         currentpicture := currentpicture shifted (w/2, 0);
1094         remember_pic := currentpicture;
1096         draw_staff (-2, 2, 0);
1097 fet_endchar;
1100 draw_shifted_too;
1103 fet_beginchar ("Semi flat", "mirroredflat");
1104         set_char_box (1.2 stafflinethickness#, .8 staff_space#,
1105                       0.6 staff_space#, 1.9 staff_space#);
1107         draw_meta_flat (0, w, 0.31 staff_space, false, false);
1108         currentpicture := currentpicture xscaled -1 shifted (w - b, 0);
1109 fet_endchar;
1112 fet_beginchar ("Semi flat", "mirroredflat.backslash");
1113         set_char_box (.4 staff_space#, .8 staff_space#,
1114                       0.6 staff_space#, 1.9 staff_space#);
1116         draw_meta_flat (0, w, 0.31 staff_space, false, false);
1118         clearxy;
1120         save slope, slash_width;
1121         slope = 0.5;
1122         slash_width = w;
1124         z11 = (0, h / 2);
1125         z12 = z11 - (slash_width, slash_width * slope) / 2;
1126         z13 = z11 + (slash_width, slash_width * slope) / 2;
1127         penpos12 (1.5 stafflinethickness, angle (z13 - z12) - 90);
1128         penpos13 (1.5 stafflinethickness, angle (z13 - z12) - 90);
1130         z14 = z12 - .75 stafflinethickness * unitvector (z13 - z12);
1131         z15 = z13 + .75 stafflinethickness * unitvector (z13 - z12);
1133         fill z13r
1134              .. z15
1135              .. z13l
1136              -- z12l
1137              .. z14
1138              .. z12r
1139              -- z13r
1140              .. cycle;
1142         currentpicture := currentpicture xscaled -1 shifted (w - b, 0);
1144         labels (1, 2, 3);
1145 fet_endchar;
1148 fet_beginchar ("Double Flat", "flatflat");
1149         save left_wid, overlap, right_wid;
1151         left_wid = .7;
1152         right_wid = .8;
1153         overlap = .05;
1155         set_char_box (1.2 stafflinethickness#,
1156                       (left_wid + right_wid - overlap) * staff_space#,
1157                       .6 staff_space#, 1.9 staff_space#);
1158         draw_meta_flat (0, left_wid * staff_space, 1/3 staff_space,
1159                         false, false);
1160         draw_meta_flat (hround ((left_wid - overlap) * staff_space),
1161                         right_wid * staff_space, 1/3 staff_space,
1162                         false, false);
1163 fet_endchar;
1166 fet_beginchar ("3/4 Flat", "flatflat.slash");
1167         save left_wid, overlap, right_wid;
1169         left_wid = .7;
1170         right_wid = .8;
1171         overlap = .05;
1173         set_char_box (1.2 stafflinethickness#,
1174                       (left_wid + right_wid - overlap) * staff_space#,
1175                       .6 staff_space#, 1.9 staff_space#);
1176         draw_meta_flat (0, left_wid * staff_space, 1/3 staff_space,
1177                         false, false);
1178         draw_meta_flat (hround ((left_wid - overlap) * staff_space),
1179                         right_wid * staff_space, 1/3 staff_space,
1180                         false, false);
1182         %% maybe we should clip part of the stems?
1183         %% or make the 1st flat smaller?
1184         %% or reverse it?
1185         pickup pencircle scaled 2 stafflinethickness;
1187         z12 = round (-.25 w - b, .55 staff_space) + feta_offset;
1188         z13 = round (.75 w, 1.45 staff_space) + feta_offset;
1189         penpos12 (2 stafflinethickness, angle (z13 - z12) - 90);
1190         penpos13 (2 stafflinethickness, angle (z13 - z12) - 90);
1192         z14 = z12 - stafflinethickness * unitvector (z13 - z12);
1193         z15 = z13 + stafflinethickness * unitvector (z13 - z12);
1195         fill z13r
1196              .. z15
1197              .. z13l
1198              -- z12l
1199              .. z14
1200              .. z12r
1201              -- z13r
1202              .. cycle;
1204         penlabels (12, 13);
1205         labels (14, 15);
1207         remember_pic := currentpicture;
1209         draw_staff (-2, 2, 0);
1210 fet_endchar;
1213 draw_shifted_too;
1216 fet_beginchar ("Double Sharp", "doublesharp");
1217         save klaverblad, klaversteel;
1218         save pat;
1219         path pat;
1221         klaversteel = 1/15 staff_space;
1222         klaverblad = .4 staff_space - .5 stafflinethickness;
1224         set_char_box (0, staff_space#, .5 staff_space#, .5 staff_space#);
1226         z1 = (klaversteel, 0);
1227         z2 = (w / 2 - klaverblad / 10, h - klaverblad);
1228         z3 = (w / 2, h);
1229         z4 = z2 reflectedabout ((0, 0), (1, 1));
1230         z5 = z1 reflectedabout ((0, 0), (1, 1));
1232         labels (1, 2, 3, 4, 5);
1234         pickup pencircle scaled blot_diameter;
1236         x2 := hfloor (rt x2) - blot_diameter / 2;
1237         x3 := hfloor (rt x3) - blot_diameter / 2;
1238         y3 := vfloor (top y3) - blot_diameter / 2;
1239         y4 := vfloor (top y4) - blot_diameter / 2;
1241         pat = (rt z1){dir45}
1242               .. {right}(bot z2)
1243               .. rt z2
1244               -- rt z3{z3 - z2}
1245               .. top z3{z4 - z3}
1246               -- top z4{z4 - z3}
1247               .. (lft z4){down}
1248               .. {dir 225}(top z5);
1249         pat := pat
1250                -- reverse pat xscaled -1 shifted (-feta_eps, 0);
1252         % assure symmetry -- it's more important to center the glyph on the
1253         % staff line than centering it between staff lines, so we use
1254         % feta_shift, not feta_space_shift.
1255         h := h + feta_shift;
1257         fill pat shifted (0, feta_shift)
1258              -- reverse pat yscaled -1 shifted (0, -feta_eps)
1259              -- cycle;
1261         % ugh
1262         currentpicture := currentpicture shifted (hround (w / 2), 0);
1264         remember_pic := currentpicture;
1266         draw_staff (-2, 2, 0);
1267 fet_endchar;
1270 draw_shifted_too;
1273 def draw_paren =
1274         save leftindent;
1276         leftindent := .2 staff_space;
1278         set_char_box (0, .5 staff_space# + stafflinethickness#,
1279                       staff_space#, staff_space#);
1281         d := d - feta_shift;
1283         z1 = (leftindent, h);
1284         z2 = (w - stafflinethickness, .5 (h - d));
1285         z3 = (leftindent, -d);
1287         penpos1 (stafflinethickness, 35);
1288         penpos2 (.1 staff_space + stafflinethickness, 0);
1289         penpos3 (stafflinethickness, -35);
1291         fill z2l{down}
1292              .. simple_serif (z3l, z3r, 90)
1293              .. z2r{up}
1294              .. simple_serif (z1r, z1l, 90)
1295              .. z2l{down}
1296              -- cycle;
1297 enddef;
1300 fet_beginchar ("Right Parenthesis", "rightparen");
1301         draw_paren;
1302         penlabels (1, 2, 3);
1304         remember_pic := currentpicture;
1306         draw_staff (-2, 2, 0);
1307 fet_endchar;
1310 draw_shifted_too;
1313 fet_beginchar ("Left Parenthesis", "leftparen");
1314         draw_paren;
1316         currentpicture := currentpicture xscaled -1;
1318         set_char_box (charwd, charbp, chardp, charht);
1319 fet_endchar;
1321 fet_endgroup ("accidentals");