Nitpick: ly:spanner-bound grob name slur -> spanner.
[lilypond.git] / mf / feta-toevallig.mf
blob48061fcd0533eaae09d74208ce95addde680720e
2 % feta-toevallig.mf -- implement Accidentals
4 % (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
9 % also show in other configuration wrt staff lines.
11 def draw_shifted_too =
12 if test > 0:
13         fet_beginchar ("shifted too", "");
14                 set_char_box (0, 0, 0, 0);
15                 currentpicture := remember_pic;
17                 draw_staff (-2, 2, 0.5);
18         fet_endchar;
19 fi;
20 enddef;
24 % Accidentals from various sources, notably
26 %   Baerenreiter edition of Schuberts `Auf dem Strom' (sharp, natural)
27 %   F Hofmeister edition of Muellers `Etueden fuer Horn' (double sharp, flat)
32 % Naming for accidentals (including microtonal variants):
34 %   SHARPBASE[.SLASHES.STEMS]
35 %   FLATBASE[.MODIFIER]
36 %  
37 % Examples:
39 %   sharp.slashslash.stem
40 %   mirroredflat.flat
45 fet_begingroup ("accidentals");
48 % Draw an arrow
50 % * `stemslant' gives the direction of the stem's left boundary
51 %   (needed for brushed stems, equals "up" for straight stems)
52 % * `extend' is used to make the stem longer or shorter (if negative);
53 %   different kinds of accidentals need different values here
55 def draw_arrow (expr attach, stemwidth, stemslant, extend, pointingdown) =
56 begingroup;
57         save htip;  % tip height
58         save wwing; % wing `radius'
59         save angle_wing_bot, angle_wing_top, angle_tip;
60         save upshift;
61         clearxy;
63         wwing := 0.26 stemwidth;
64         htip := staff_space * 0.85 + stafflinethickness - wwing;
66         % `flip' is used to reflect the arrow vertically
67         % if arrow points downward
68         transform flip;
69         if pointingdown:
70                 flip = identity reflectedabout (origin, right);
71         else:
72                 flip = identity;
73         fi;
75         z1 = attach shifted (-stemwidth / 2, 0);
76         upshift := max (0, wwing + 0.1 staff_space + extend);
77         z2 = z1 shifted (((unitvector stemslant)
78                           scaled upshift) transformed flip);
80         z7 = attach shifted ((stemwidth/2),0);
81         z6 = z7 shifted (((unitvector (-xpart stemslant, ypart stemslant))
82                           scaled upshift) transformed flip);
83         z2 - z3 = ( 0.38 staff_space, 0.05 htip) transformed flip;
84         z6 - z5 = (-0.38 staff_space, 0.05 htip) transformed flip;
86         z4 = attach shifted ((-0.2 stemwidth, upshift + htip)
87                              transformed flip);
88         z4'= attach shifted (( 0.2 stemwidth, upshift + htip)
89                              transformed flip);
91         % `angle_wing_bot' is the angle at which the arc
92         % from z2 to z3a enters z3a
93         % `angle_wing_top' is the angle at which the arc
94         % from z3b to z4 leaves z3b
95         % `angle_tip' is the angle at which the arc
96         % from z4 to z4' leaves z4
97         angle_wing_bot = 30;
98         angle_wing_top = 55;
99         angle_tip = 68;
101         z3a = z3 shifted ((((dir angle_wing_bot) rotated -90)
102                            scaled wwing) transformed flip);
103         z3b = z3 shifted ((((dir angle_wing_top) rotated 90)
104                            scaled wwing) transformed flip);
106         z5a = z5 shifted ((((dir (180 - angle_wing_bot)) rotated 90)
107                            scaled wwing) transformed flip);
108         z5b = z5 shifted ((((dir (180 - angle_wing_top)) rotated -90)
109                            scaled wwing) transformed flip);
111         % Draw the arrow
112         pickup pencircle scaled 1;
113         fill z1
114              -- z2{stemslant transformed flip}
115              .. {(-dir angle_wing_bot) transformed flip}z3a
116              .. z3b{(dir angle_wing_top) transformed flip}
117              .. z4{(dir angle_tip) transformed flip}
118              .. z4'{(dir (-angle_tip)) transformed flip}
119              .. {(dir (-angle_wing_top)) transformed flip}z5b
120              .. z5a{(-dir (-angle_wing_bot)) transformed flip}
121              .. z6{((-stemslant) reflectedabout (origin, up)) transformed flip}
122              -- z7
123              -- cycle;
125         labels (range 0 thru 7, 4', 3a, 3b, 5a, 5b);
126 endgroup;
127 enddef;
129 save remember_pic;
130 picture remember_pic;
132 save sharp_beamheight;
133 sharp_beamheight# := 0.3 staff_space# + stafflinethickness#;
136 % The beams of most sharps have horizontal endings (as if drawn with
137 % a square pen).  [Wanske] does not mention this, so we'll just ignore
138 % this fact.
141 def draw_meta_sharp (expr width, offset) =
142         save beamwidth, beamslope;
143         save ne, nw_dist;
144         pair ne, nw_dist;
146         beamwidth := width;
148         define_whole_vertical_blacker_pixels (sharp_beamheight);
150         clearxy;
152         beamslope = sharp_beamheight / beamwidth;
154         pickup pencircle scaled 2 blot_diameter;
156         rt x2 - lft x1 = beamwidth;
157         z2 = z1 + whatever * (beamwidth, sharp_beamheight);
158         .5 [z1, z3] = (.5 w, offset);
159         x3 = x2;
160         top y2 - bot y3 = sharp_beamheight;
161         x4 = x1;
162         top y1 - bot y4 = sharp_beamheight;
164         ne = unitvector (z2 - z1);
165         nw_dist = (ne rotated 90) * blot_diameter;
167         fill lft z1{up}
168              ... (z1 + nw_dist){ne}
169              -- (z2 + nw_dist){ne}
170              ... rt z2{down}
171              -- rt z3{down}
172              ... (z3 - nw_dist){-ne}
173              -- (z4 - nw_dist){-ne}
174              ... lft z4{up}
175              -- cycle;
177         labels (1, 2, 3, 4);
178 enddef;
181 def draw_sharp(expr arrowup, arrowdown) =
182         save stem, stemx, stemwidth;
183         save outer_space, interbeam;
184         save stemlength, extendleft, extendright, height, depth;
186         stemwidth# := stafflinethickness# + .05 staff_space#;
187         define_whole_blacker_pixels (stemwidth);
189         interbeam := 1.05 staff_space_rounded;
191         stemlength# := 1.5 staff_space#;
192         define_pixels (stemlength);
194         height# = stemlength#;
195         depth# = stemlength#;
196         extendright# = 0;
197         extendleft# = 0;
198         if arrowup:
199                 height# := height# + 1.2 staff_space#;
200                 extendright# := extendright# + 1.5 stafflinethickness#;
201         fi;
202         if arrowdown:
203                 depth# := depth# + 1.2 staff_space#;
204                 extendleft# := extendleft# + 1.5 stafflinethickness#;
205         fi;
206         define_pixels (extendleft, extendright);
207         set_char_box (extendleft#, 1.1 staff_space#, depth#, height#);
209         stem := 7 / 16 * w;
210         stemx := hround stem;
211         outer_space := hround ((w - stemx - stemwidth) / 2);
213         w := 2 outer_space + stemx + stemwidth;
214         d := d - feta_space_shift;
216         draw_meta_sharp (w, -.5 interbeam);
217         draw_meta_sharp (w, -.5 interbeam + vround interbeam);
219         % expand the charbox so that it encloses the whole arrow;
220         % this must not happen earlier because some commands above
221         % still rely on the old width
222         w := w + extendright;
224         pickup pencircle scaled stemwidth;
226         lft x5 = lft x6 = outer_space;
227         lft x7 = lft x8 = outer_space + stemx;
228         bot y5 = -stemlength;
229         top y6 = vround (1.5 staff_space - stem * beamslope);
230         bot y7 = -top y6 + feta_space_shift;
231         top y8 = stemlength;
233         labels (5, 6, 7, 8);
235         draw_gridline (z5, z6, stemwidth);
236         draw_gridline (z7, z8, stemwidth);
238         if arrowup:
239                 draw_arrow (z8, stemwidth, up,
240                             stafflinethickness / 2 + stemwidth / 2, false);
241         fi;
242         if arrowdown:
243                 draw_arrow (z5, stemwidth, up,
244                             stafflinethickness / 2 + stemwidth / 2, true);
245         fi;
247         remember_pic := currentpicture;
249         draw_staff (-2, 2, 0);
250 enddef;
253 fet_beginchar ("Sharp", "sharp");
254         draw_sharp (false, false);
255 fet_endchar;
258 draw_shifted_too;
261 fet_beginchar ("Arrowed Sharp (arrow up)", "sharp.arrowup");
262         draw_sharp (true, false);
263 fet_endchar;
266 draw_shifted_too;
269 fet_beginchar ("Arrowed Sharp (arrow down)", "sharp.arrowdown");
270         draw_sharp (false, true);
271 fet_endchar;
274 draw_shifted_too;
277 fet_beginchar ("Arrowed Sharp (arrows up and down)", "sharp.arrowboth");
278         draw_sharp (true, true);
279 fet_endchar;
282 draw_shifted_too;
285 fet_beginchar ("1/2 Sharp", "sharp.slashslash.stem");
286         save stem, stemwidth;
287         save outer_space, interbeam;
289         stemwidth# := stafflinethickness# + .05 staff_space#;
290         define_whole_blacker_pixels (stemwidth);
292         interbeam := 1.05 staff_space_rounded;
294         set_char_box (0, 0.7 staff_space#,
295                       1.5 staff_space#, 1.5 staff_space#);
297         stem := 7 / 16 * w;
298         outer_space := hround ((w - stemwidth) / 2);
300         w := 2 outer_space + stemwidth;
301         d := d - feta_space_shift;
303         draw_meta_sharp (w, -.5 interbeam);
304         draw_meta_sharp (w, -.5 interbeam + vround interbeam);
306         pickup pencircle scaled stemwidth;
308         lft x5 = lft x6 = outer_space;
309         top y6 = vround (1.5 staff_space - .5 stem);
310         bot y5 = -top y6 + feta_space_shift;
312         labels (5, 6);
314         draw_gridline (z5, z6, stemwidth);
316         remember_pic := currentpicture;
318         draw_staff (-2, 2, 0);
319 fet_endchar;
322 draw_shifted_too;
325 fet_beginchar ("Sharp (3 beams)", "sharp.slashslashslash.stemstem");
326         save stem, stemx, stemwidth;
327         save outer_space, interbeam;
328         save sharp_beamheight;
330         sharp_beamheight# := 0.22 staff_space# + stafflinethickness#;
332         stemwidth# := stafflinethickness# + .05 staff_space#;
333         define_whole_blacker_pixels (stemwidth);
335         interbeam := 1.2 staff_space_rounded;
337         set_char_box (0, 1.1 staff_space#,
338                       1.5 staff_space#, 1.5 staff_space#);
340         stem := 7 / 16 * w;
341         stemx := hround stem;
342         outer_space := hround ((w - stemx - stemwidth) / 2);
344         w := 2 outer_space + stemx + stemwidth;
345         d := d - feta_space_shift;
347         draw_meta_sharp (.88 w, -.5 interbeam);
348         draw_meta_sharp (.88 w, -.5 interbeam + vround interbeam);
349         sharp_beamheight# := 1/.88 sharp_beamheight#;
350         draw_meta_sharp (w, 0);
352         pickup pencircle scaled stemwidth;
354         lft x5 = lft x6 = outer_space;
355         lft x7 = lft x8 = outer_space + stemx;
356         bot y5 = -d;
357         top y6 = vround (1.5 staff_space - stem * beamslope);
358         bot y7 = -top y6 + feta_space_shift;
359         top y8 = h;
361         labels (5, 6, 7, 8);    
363         draw_gridline (z5, z6, stemwidth);
364         draw_gridline (z7, z8, stemwidth);
366         remember_pic := currentpicture;
368         draw_staff (-2, 2, 0);
369 fet_endchar;
372 draw_shifted_too;
375 fet_beginchar ("1/2 Sharp (3 beams)", "sharp.slashslashslash.stem");
376         save stem, stemx, stemwidth;
377         save outer_space, interbeam;
378         save sharp_beamheight;
380         sharp_beamheight# := 0.22 staff_space# + stafflinethickness#;
382         stemwidth# := stafflinethickness# + .05 staff_space#;
383         define_whole_blacker_pixels (stemwidth);
385         interbeam := 1.2 staff_space_rounded;
387         set_char_box (0, 0.95 staff_space#,
388                       1.3 staff_space#, 1.3 staff_space#);
390         stem := 7 / 16 * w;
391         outer_space := hround ((w - stemwidth) / 2);
393         w := 2 outer_space + stemwidth;
394         d := d - feta_space_shift;
396         draw_meta_sharp (.8 w, -.5 interbeam);
397         draw_meta_sharp (.8 w, -.5 interbeam + vround interbeam);
398         sharp_beamheight# := 1/.8 sharp_beamheight#;
399         draw_meta_sharp (w, 0);
401         pickup pencircle scaled stemwidth;
403         lft x5 = lft x6 = outer_space;
404         top y6 = vround (1.5 staff_space - .5 stem);
405         bot y5 = -top y6 + feta_space_shift;
406         labels (5, 6);
408         draw_gridline (z5, z6, stemwidth);
410         remember_pic := currentpicture;
412         draw_staff (-2, 2, 0);
413 fet_endchar;
416 draw_shifted_too;
419 fet_beginchar ("3/4 Sharp", "sharp.slashslash.stemstemstem");
420         save stem, stemx, stemwidth;
421         save outer_space, interbeam;
423         stemwidth# := stafflinethickness# + .05 staff_space#;
424         define_whole_blacker_pixels (stemwidth);
426         interbeam := 1.05 staff_space_rounded;
428         set_char_box (0, 1.6 staff_space#,
429                       1.5 staff_space#, 1.5 staff_space#);
431         stem := 9 / 32 * w;
432         stemx := hround stem;
433         outer_space := hround ((w - 2 stemx - stemwidth) / 2);
435         w := 2 outer_space + 2 stemx + stemwidth;
436         d := d - feta_space_shift;
438         draw_meta_sharp (w, -.5 interbeam);
439         draw_meta_sharp (w, -.5 interbeam + vround interbeam);
441         pickup pencircle scaled stemwidth;
443         lft x5 = lft x6 = outer_space;
444         lft x7 = lft x8 = outer_space + stemx;
445         lft x9 = lft x10 = outer_space + 2 stemx;
446         bot y5 = -d;
447         top y6 = vround (1.5 staff_space - 2 stem * beamslope);
448         bot y9 = -top y6 + feta_space_shift;
449         top y10 = h;
450         y7 = .5 [y5, y9];
451         y8 = .5 [y6, y10];
453         labels (5, 6, 7, 8, 9, 10);
455         draw_gridline (z5, z6, stemwidth);
456         draw_gridline (z7, z8, stemwidth);
457         draw_gridline (z9, z10, stemwidth);
459         remember_pic := currentpicture;
461         draw_staff (-2, 2, 0);
462 fet_endchar;
465 draw_shifted_too;
469 % The stems of the natural are brushed (at least, in Barenreiter SCS)
472 def draw_natural (expr arrowup, arrowdown) =
473         save stemwidth, top_stem_thick;
474         save ne, pat_top, pat_bottom;
475         save depth, height, extendleft, extendright, stemlength;
476         save brush_scale_up, brush_scale_down;
477         pair ne;
478         path pat_top, pat_bottom;
480         top_stem_thick# = stafflinethickness# + .10 staff_space#;
481         stemwidth# = 0.09 staff_space# + .5 stafflinethickness#;
482         define_whole_blacker_pixels (top_stem_thick, stemwidth);
484         stemlength# = 1.5 staff_space#;
485         define_pixels (stemlength);
487         height# = stemlength#;
488         depth# = stemlength#;
489         extendleft# = 0;
490         extendright# = 0;
491         if arrowup:
492                 extendleft# := 3 stafflinethickness#;
493                 height# := height# + 1.2 staff_space#;
494         fi;
495         if arrowdown:
496                 extendright# := 3.15 stafflinethickness#;
497                 depth# := depth# + 1.2 staff_space#;
498         fi;
499         define_pixels (extendright);
501         set_char_box (extendleft#, 2/3 staff_space#, depth#, height#);
503         d := d - feta_space_shift;
505         pickup pencircle scaled stemwidth;
507         brush_scale_up := 1.0;
508         brush_scale_down := 1.0;
509         % to look nice, arrowed stems must be less brushed
510         if arrowup:
511                 brush_scale_up := 0.85;
512         fi;
513         if arrowdown:
514                 brush_scale_down := 0.85;
515         fi;
517         penpos1 (top_stem_thick, 0);
518         penpos3 (top_stem_thick, 0);
519         penpos2 (stemwidth, 0);
520         penpos4 (stemwidth, 0);
521         % z1' and z3' are needed for the arrowed accidentals
522         penpos1' (top_stem_thick * brush_scale_up, 0);
523         penpos3' (top_stem_thick * brush_scale_down, 0);
525         x2r = w;
526         x4l = 0;
527         x3 = x3' = x2;
528         x1 = x1' = x4;
530         y1 = y1' = stemlength;
531         y3 = y3' = -stemlength;
532         top y2 = vround (staff_space - 3/2 stafflinethickness);
533         y4 = -y2 + feta_space_shift;
535         pat_bottom := z4r{z4r - z1r}
536                       .. bot z4
537                       .. z4l{z1l - z4l};
538         fill simple_serif (z1'l, z1'r, -30)
539              -- pat_bottom
540              -- cycle;
542         pat_top := z2r{z2r - z3r}
543                    .. top z2
544                    .. z2l{z3l - z2l};
545         fill simple_serif (z3'l, z3'r, 30)
546              -- pat_top
547              -- cycle;
549         ne = (x2 - x4, stafflinethickness);
551         z11' = z3l + whatever * (z2l - z3l);
552         y11' = vround (.5 (staff_space - stafflinethickness));
553         z11 = z11' + whatever * ne;
554         x11 = x12;
555         z12 = directionpoint -ne of pat_top;
556         z13 = z12 + whatever * ne;
557         x13 = x1;
558         z14 = z11 + whatever * ne;
559         x14 = x1;
561         z21' = z4r + whatever * (z1r - z4r);
562         y21' = -y11' + feta_space_shift;
563         z21 = z21' + whatever * ne;
564         x21 = x22;
565         z22 = directionpoint -ne of pat_bottom;
566         z23 = z22 + whatever * ne;
567         x23 = x3;
568         z24 = z21 + whatever * ne;
569         x24 = x3;
571         fill z11
572              -- z12
573              -- z13
574              -- z14
575              -- cycle;
576         fill z21
577              -- z22
578              -- z23
579              -- z24
580              -- cycle;
582         penlabels (1, 1', 2, 3, 3', 4);
583         labels (11, 11', 12, 13, 14, 21, 21', 22, 23, 24);
585         if arrowup:
586                 draw_arrow (z1, top_stem_thick * brush_scale_up,
587                             z1'l - z4l, stafflinethickness / 2, false);
588         fi;
589         if arrowdown:
590                 draw_arrow (z3, top_stem_thick * brush_scale_down,
591                             z2r - z3'r, stafflinethickness / 2, true);
592                 w := w + extendright;
593         fi;
595         remember_pic := currentpicture;
597         draw_staff (-2, 2, 0);
598 enddef;
601 fet_beginchar ("Natural", "natural");
602         draw_natural (false, false);
603 fet_endchar;
606 draw_shifted_too;
609 fet_beginchar ("Arrowed Natural (arrow up)", "natural.arrowup");
610         draw_natural (true, false);
611 fet_endchar;
614 draw_shifted_too;
617 fet_beginchar ("Arrowed Natural (arrow down)", "natural.arrowdown");
618         draw_natural (false, true);
619 fet_endchar;
622 draw_shifted_too;
625 fet_beginchar ("Arrowed Natural (arrows up and down)", "natural.arrowboth");
626         draw_natural (true, true);
627 fet_endchar;
630 draw_shifted_too;
634 % Dedicated to my mom.    (3/10/97)
636 % Mamma, ik hou van je; kom je alsjeblieft terug?
637 %    -- HW
640 % TODO: remove crook_fatness
641 % TODO: document, simplify!
644 def draw_meta_flat (expr xcenter, w, crook_fatness, arrowup, arrowdown) =
645         save crook_thinness;
646         save bottom_overshoot, bot_crook_dir;
647         save top_stem_thick, top_stem_thick_orig;
648         save bottom_stem_thick, hair, smaller_hole;
649         save top_crook_thinness;
650         save zwiep;
651         save center;
652         pair center, bot_crook_dir;
653         save clearing, clearing_orig;
655         clearxy;
657         % the stem shouldn't reach the top staff line.
658         %% TODO: should take from height.
659         %
660         % TODO: parameterize this
661         %
662         if w >= 0.75 staff_space:
663                 smaller_hole = 0.35 stafflinethickness;
664         else:
665                 smaller_hole = 0;
666         fi;
667         crook_thinness = .7 stafflinethickness + .06 staff_space;
668         top_crook_thinness = 1 stafflinethickness + .065 staff_space;
669         clearing = 1.7 stafflinethickness;
670         clearing_orig = clearing;
671         if arrowup:
672                 clearing := 0.5 staff_space;
673         fi;
674         bottom_overshoot = stafflinethickness;
676         bottom_stem_thick# = 0.06 staff_space# + 0.6 stafflinethickness#;
677         top_stem_thick# = 0.1 staff_space# + 1.2 stafflinethickness#;
678         top_stem_thick_orig# = top_stem_thick#;
679         if arrowup:
680                 % to look nice, arrowed stems should be less brushed
681                 top_stem_thick# := top_stem_thick# * 0.8;
682         fi;
683         define_whole_blacker_pixels (bottom_stem_thick, top_stem_thick,
684                                      top_stem_thick_orig);
686         if odd (top_stem_thick - bottom_stem_thick):
687                 top_stem_thick := top_stem_thick - 1;
688         fi;
689         if odd (top_stem_thick_orig - bottom_stem_thick):
690                 top_stem_thick_orig := top_stem_thick_orig - 1;
691         fi;
693         center = (xcenter, 0);
695         x1l = hround (xcenter - .5 top_stem_thick);
696         y1 = vround (2 staff_space - clearing);
697         x2l = hround (xcenter - .5 bottom_stem_thick);
698         y2 = -.5 staff_space - .5 stafflinethickness;
699         % z16 and the `*_orig' variables are needed for arrowed accidentals
700         % because their inner part should be unchanged from plain ones but
701         % the points z3l, z3r, and z10 depend on values that are different
702         % for arrowed accidentals
703         x16l = hround (xcenter -.5 top_stem_thick_orig);
704         y16 = vround (2 staff_space - clearing_orig);
706         penpos1 (top_stem_thick, 0);
707         penpos16 (top_stem_thick_orig, 0);
708         penpos2 (bottom_stem_thick, 0);
710         y3l = vfloor ((staff_space - stafflinethickness) / 2);
711         z3l = whatever [z2r, z1r];
712         z3r = .3 [z2r,
713                   (z16r shifted (0, clearing_orig - 1.7 stafflinethickness))]
714               + (smaller_hole, 0);
715         x3r := hceiling x3r;
717         % we insert z3l to get better conversion with mf2pt1
718         fill simple_serif (z1r, z1l, 30)
719              -- z2l
720              -- z2r
721              -- z3l
722              -- cycle;
724         z10 = whatever [z2r, z16r] + (smaller_hole, 0);
725         y10 = -1/10 staff_space;
726         x10 := hceiling x10;
728         x11 = xcenter + bottom_overshoot / 3;
729         y11 = -vround (.5 (staff_space + stafflinethickness)
730                        + bottom_overshoot);
732         x2a = 0.2[x2r, x7];
733         y2a = 1.5[y2, y11];
735         penpos4 (whatever, 53);
737         y4l - y4r = top_crook_thinness;
738         y5r = .15 staff_space;
739         x5l = hround (w + xcenter);
740         y4 = staff_space / 2;
741         x4r = .45 [x5r, x3r];
742         y4l := vround y4l;
744         penpos5 (crook_fatness, -175);
746         bot_crook_dir = unitvector ((x5l, 0) - z11);
747         z8 = z11 + whatever * bot_crook_dir;
748         y8 = -staff_space / 2;
750         z7 = z8
751              + whatever * bot_crook_dir
752              + crook_thinness * (bot_crook_dir rotated 90);
753         x7 = .1 [x3r, x8];
755         unfill z3r{z3r - z10}
756                .. z4r{right}
757                .. z5r{down}
758                .. z7{-bot_crook_dir}
759                & z7
760                .. z10{z3r - z10}
761                -- cycle;
763         if arrowdown:
764                 fill z2l{down}
765                      .. z2a{up}
766                      .. z8{bot_crook_dir}
767                      .. z5l{up}
768                      .. z4l{left}
769                      .. z3l
770                      -- cycle;
771         else:
772                 fill z2l{down}
773                      .. z11{right}
774                      .. z8{bot_crook_dir}
775                      .. z5l{up}
776                      .. z4l{left}
777                      .. z3l
778                      -- cycle;
779         fi;
781         if arrowup:
782                 draw_arrow (z1, top_stem_thick, z1l - z2l,
783                             0.5 stafflinethickness, false);
784         fi;
785         if arrowdown:
786                 draw_arrow ((0.5 [x2l, x2a], y2), x2a - x2l, up,
787                             staff_space / 2, true);
788         fi;
789 enddef;
792 def draw_arrowed_meta_flat (expr xcenter, width, crook_fatness,
793                                  arrowup, arrowdown) =
794         save depth, height, extendleft;
796         depth# = 0.6 staff_space#;
797         height# = 1.9 staff_space#;
798         extendleft# := 1.2 stafflinethickness#;
799         if arrowup:
800                 extendleft# := 3.45 stafflinethickness#;
801                 height# := height# + 0.8 staff_space#;
802         fi;
803         if arrowdown:
804                 extendleft# := 3.45 stafflinethickness#;
805                 depth# := depth# + 1.6 staff_space#;
806         fi;
808         set_char_box (extendleft#, width, depth#, height#);
809         draw_meta_flat(xcenter, w, crook_fatness, arrowup, arrowdown);
810 enddef;
813 % unfortunately, 600dpi is not enough to show the brush of the stem.
816 fet_beginchar ("Flat", "flat");
817         draw_arrowed_meta_flat (0, 0.8 staff_space#, 0.31 staff_space,
818                                 false, false);
819         penlabels (range 0 thru 11);
821         remember_pic := currentpicture;
823         draw_staff (-2, 2, 0);
824 fet_endchar;
827 draw_shifted_too;
830 fet_beginchar ("Arrowed Flat (arrow up)", "flat.arrowup");
831         draw_arrowed_meta_flat (0, 0.8 staff_space#, 0.31 staff_space,
832                                 true, false);
833         penlabels (range 0 thru 23);
835         remember_pic := currentpicture;
837         draw_staff (-2, 2, 0);
838 fet_endchar;
841 draw_shifted_too;
844 fet_beginchar ("Arrowed Flat (arrow down)", "flat.arrowdown");
845         draw_arrowed_meta_flat (0, 0.8 staff_space#, 0.31 staff_space,
846                                 false, true);
847         penlabels (range 0 thru 23);
849         remember_pic := currentpicture;
851         draw_staff (-2, 2, 0);
852 fet_endchar;
855 draw_shifted_too;
858 fet_beginchar ("Arrowed Flat (arrow up and down)", "flat.arrowboth");
859         draw_arrowed_meta_flat (0, 0.8 staff_space#, 0.31 staff_space,
860                                 true, true);
861         penlabels (range 0 thru 23);
863         remember_pic := currentpicture;
865         draw_staff (-2, 2, 0);
866 fet_endchar;
869 draw_shifted_too;
872 fet_beginchar ("Flat (slashed)", "flat.slash");
873         set_char_box (.4 staff_space#, .8 staff_space#,
874                       0.6 staff_space#, 1.9 staff_space#);
876         draw_meta_flat (0, w, 0.31 staff_space, false, false);
878         clearxy;
880         save slope, slash_width;
881         slope = 0.5;
882         slash_width = w;
884         z11 = (0, h / 2);
885         z12 = z11 - (slash_width, slash_width * slope) / 2;
886         z13 = z11 + (slash_width, slash_width * slope) / 2;
887         penpos12 (1.5 stafflinethickness, angle (z13 - z12) - 90);
888         penpos13 (1.5 stafflinethickness, angle (z13 - z12) - 90);
890         z14 = z12 - .75 stafflinethickness * unitvector (z13 - z12);
891         z15 = z13 + .75 stafflinethickness * unitvector (z13 - z12);
893         fill z13r
894              .. z15
895              .. z13l
896              -- z12l
897              .. z14
898              .. z12r
899              -- z13r
900              .. cycle;
902         penlabels (12, 13);
903         labels (14, 15);
905         remember_pic := currentpicture;
907         draw_staff (-2, 2, 0);
908 fet_endchar;
911 fet_beginchar ("Flat (slashed twice)", "flat.slashslash");
912         set_char_box (.4 staff_space#, .8 staff_space#,
913                       0.6 staff_space#, 1.9 staff_space#);
915         draw_meta_flat (0, w, 0.31 staff_space, false, false);
917         clearxy;
919         save slope, slash_width;
920         slope = 0.5;
921         slash_width = w;
923         z11 = (0, 5/12 h);
924         z12 = z11 - (slash_width, slash_width * slope) / 2;
925         z13 = z11 + (slash_width, slash_width * slope) / 2;
926         penpos12 (1.5 stafflinethickness, angle (z13 - z12) - 90);
927         penpos13 (1.5 stafflinethickness, angle (z13 - z12) - 90);
929         z14 = z12 - .75 stafflinethickness * unitvector (z13 - z12);
930         z15 = z13 + .75 stafflinethickness * unitvector (z13 - z12);
932         fill z13r
933              .. z15
934              .. z13l
935              -- z12l
936              .. z14
937              .. z12r
938              -- z13r
939              .. cycle;
941         penlabels (12, 13);
942         labels (14, 15);
944         z21 = (0, 2/3 h);
945         z22 = z21 - (slash_width, slash_width * slope) / 2;
946         z23 = z21 + (slash_width, slash_width * slope) / 2;
947         penpos22 (1.5 stafflinethickness, angle (z23 - z22) - 90);
948         penpos23 (1.5 stafflinethickness, angle (z23 - z22) - 90);
950         z24 = z22 - .75 stafflinethickness * unitvector (z23 - z22);
951         z25 = z23 + .75 stafflinethickness * unitvector (z23 - z22);
953         fill z23r
954              .. z25
955              .. z23l
956              -- z22l
957              .. z24
958              .. z22r
959              -- z23r
960              .. cycle;
962         penlabels (22, 23);
963         labels (24, 25);
965         remember_pic := currentpicture;
967         draw_staff (-2, 2, 0);
968 fet_endchar;
971 fet_beginchar ("Flatflat (mirrored)", "mirroredflat.flat");
972         set_char_box (0, 1.6 staff_space#, 
973                       0.6 staff_space#, 1.9 staff_space#);
975         % This is a modified version of `draw_meta_flat'.
977         save crook_thinness, crook_fatness;
978         save bottom_overshoot, bot_crook_dir;
979         save top_stem_thick, bottom_stem_thick, hair, smaller_hole;
980         save top_crook_thinness;
981         save zwiep;
982         save center;
983         pair center, bot_crook_dir;
984         save clearing, wid;
985         save pat;
986         path pat;
988         clearxy;
990         wid = w / 2;
992         % the stem shouldn't reach the top staff line.
993         %% TODO: should take from height.
994         %
995         % TODO: parameterize this
996         %
997         if wid >= 0.75 staff_space:
998                 smaller_hole = 0.35 stafflinethickness;
999         else:
1000                 smaller_hole = 0;
1001         fi;
1002         clearing = 1.7 stafflinethickness;
1003         crook_thinness = .7 stafflinethickness + .06 staff_space;
1004         crook_fatness = 0.31 staff_space;
1005         top_crook_thinness = 1 stafflinethickness + .065 staff_space;
1006         bottom_overshoot = stafflinethickness;
1008         bottom_stem_thick# = 0.06 staff_space# + 0.6 stafflinethickness#;
1009         top_stem_thick# = 0.1 staff_space# + 1.2 stafflinethickness#;
1010         define_whole_blacker_pixels (bottom_stem_thick, top_stem_thick);
1012         if odd (top_stem_thick - bottom_stem_thick):
1013                 top_stem_thick := top_stem_thick - 1;
1014         fi;
1016         center = (0, 0);
1018         x1l = hround (-.5 top_stem_thick);
1019         y1 = vround (2 staff_space - clearing);
1020         x2l = hround (-.5 bottom_stem_thick);
1021         y2 = -.5 staff_space - .5 stafflinethickness;
1023         penpos1 (top_stem_thick, 0);
1024         penpos2 (bottom_stem_thick, 0);
1026         y3l = vfloor ((staff_space - stafflinethickness) / 2);
1027         z3l = whatever [z2r, z1r];
1028         z3r = .3 [z2r, z1r] + (smaller_hole, 0);
1029         x3r := hceiling x3r;
1031         z10 = whatever [z2r, z1r] + (smaller_hole, 0);
1032         y10 = -1/10 staff_space;
1033         x10 := hceiling x10;
1035         x11 = bottom_overshoot / 3;
1036         y11 = -vround (.5 (staff_space + stafflinethickness)
1037                        + bottom_overshoot);
1039         penpos4 (whatever, 53);
1041         y4l - y4r = top_crook_thinness;
1042         y5r = .15 staff_space;
1043         x5l = hround (wid);
1044         y4 = staff_space / 2;
1045         x4r = .45 [x5r, x3r];
1046         y4l := vround y4l;
1048         penpos5 (crook_fatness, -175);
1050         bot_crook_dir = unitvector ((x5l, 0) - z11);
1051         z8 = z11 + whatever * bot_crook_dir;
1052         y8 = -staff_space / 2;
1054         z7 = z8
1055              + whatever * bot_crook_dir
1056              + crook_thinness * (bot_crook_dir rotated 90);
1057         x7 = .1 [x3r, x8];
1059         pat := z3r{z3r - z10}
1060                .. z4r{right}
1061                .. z5r{down}
1062                .. z7{-bot_crook_dir}
1063                & z7
1064                .. z10{z3r - z10}
1065                -- cycle;
1066         unfill pat;
1067         unfill pat xscaled -1;
1069         pat := z11{right}
1070                .. z8{bot_crook_dir}
1071                .. z5l{up}
1072                .. z4l{left}
1073                .. z3l;
1074         fill pat
1075              -- simple_serif (z1r, z1l, 30)
1076              -- reverse pat xscaled -1 shifted (-feta_eps, 0)
1077              -- cycle;
1079         currentpicture := currentpicture shifted (w/2, 0);
1081         remember_pic := currentpicture;
1083         draw_staff (-2, 2, 0);
1084 fet_endchar;
1087 draw_shifted_too;
1090 fet_beginchar ("Semi flat", "mirroredflat");
1091         set_char_box (1.2 stafflinethickness#, .8 staff_space#,
1092                       0.6 staff_space#, 1.9 staff_space#);
1094         draw_meta_flat (0, w, 0.31 staff_space, false, false);
1095         currentpicture := currentpicture xscaled -1 shifted (w - b, 0);
1096 fet_endchar;
1099 fet_beginchar ("Semi flat", "mirroredflat.backslash");
1100         set_char_box (.4 staff_space#, .8 staff_space#,
1101                       0.6 staff_space#, 1.9 staff_space#);
1103         draw_meta_flat (0, w, 0.31 staff_space, false, false);
1105         clearxy;
1107         save slope, slash_width;
1108         slope = 0.5;
1109         slash_width = w;
1111         z11 = (0, h / 2);
1112         z12 = z11 - (slash_width, slash_width * slope) / 2;
1113         z13 = z11 + (slash_width, slash_width * slope) / 2;
1114         penpos12 (1.5 stafflinethickness, angle (z13 - z12) - 90);
1115         penpos13 (1.5 stafflinethickness, angle (z13 - z12) - 90);
1117         z14 = z12 - .75 stafflinethickness * unitvector (z13 - z12);
1118         z15 = z13 + .75 stafflinethickness * unitvector (z13 - z12);
1120         fill z13r
1121              .. z15
1122              .. z13l
1123              -- z12l
1124              .. z14
1125              .. z12r
1126              -- z13r
1127              .. cycle;
1129         currentpicture := currentpicture xscaled -1 shifted (w - b, 0);
1131         labels (1, 2, 3);
1132 fet_endchar;
1135 fet_beginchar ("Double Flat", "flatflat");
1136         save left_wid, overlap, right_wid;
1138         left_wid = .7;
1139         right_wid = .8;
1140         overlap = .05;
1142         set_char_box (1.2 stafflinethickness#,
1143                       (left_wid + right_wid - overlap) * staff_space#,
1144                       .6 staff_space#, 1.9 staff_space#);
1145         draw_meta_flat (0, left_wid * staff_space, 1/3 staff_space,
1146                         false, false);
1147         draw_meta_flat (hround ((left_wid - overlap) * staff_space),
1148                         right_wid * staff_space, 1/3 staff_space,
1149                         false, false);
1150 fet_endchar;
1153 fet_beginchar ("3/4 Flat", "flatflat.slash");
1154         save left_wid, overlap, right_wid;
1156         left_wid = .7;
1157         right_wid = .8;
1158         overlap = .05;
1160         set_char_box (1.2 stafflinethickness#,
1161                       (left_wid + right_wid - overlap) * staff_space#,
1162                       .6 staff_space#, 1.9 staff_space#);
1163         draw_meta_flat (0, left_wid * staff_space, 1/3 staff_space,
1164                         false, false);
1165         draw_meta_flat (hround ((left_wid - overlap) * staff_space),
1166                         right_wid * staff_space, 1/3 staff_space,
1167                         false, false);
1169         %% maybe we should clip part of the stems?
1170         %% or make the 1st flat smaller?
1171         %% or reverse it?
1172         pickup pencircle scaled 2 stafflinethickness;
1174         z12 = round (-.25 w - b, .55 staff_space) + feta_offset;
1175         z13 = round (.75 w, 1.45 staff_space) + feta_offset;
1176         penpos12 (2 stafflinethickness, angle (z13 - z12) - 90);
1177         penpos13 (2 stafflinethickness, angle (z13 - z12) - 90);
1179         z14 = z12 - stafflinethickness * unitvector (z13 - z12);
1180         z15 = z13 + stafflinethickness * unitvector (z13 - z12);
1182         fill z13r
1183              .. z15
1184              .. z13l
1185              -- z12l
1186              .. z14
1187              .. z12r
1188              -- z13r
1189              .. cycle;
1191         penlabels (12, 13);
1192         labels (14, 15);
1194         remember_pic := currentpicture;
1196         draw_staff (-2, 2, 0);
1197 fet_endchar;
1200 draw_shifted_too;
1203 fet_beginchar ("Double Sharp", "doublesharp");
1204         save klaverblad, klaversteel;
1205         save pat;
1206         path pat;
1208         klaversteel = 1/15 staff_space;
1209         klaverblad = .4 staff_space - .5 stafflinethickness;
1211         set_char_box (0, staff_space#, .5 staff_space#, .5 staff_space#);
1213         z1 = (klaversteel, 0);
1214         z2 = (w / 2 - klaverblad / 10, h - klaverblad);
1215         z3 = (w / 2, h);
1216         z4 = z2 reflectedabout ((0, 0), (1, 1));
1217         z5 = z1 reflectedabout ((0, 0), (1, 1));
1219         labels (1, 2, 3, 4, 5);
1221         pickup pencircle scaled blot_diameter;
1223         x2 := hfloor (rt x2) - blot_diameter / 2;
1224         x3 := hfloor (rt x3) - blot_diameter / 2;
1225         y3 := vfloor (top y3) - blot_diameter / 2;
1226         y4 := vfloor (top y4) - blot_diameter / 2;
1228         pat = (rt z1){dir45}
1229               .. {right}(bot z2)
1230               .. rt z2
1231               -- rt z3{z3 - z2}
1232               .. top z3{z4 - z3}
1233               -- top z4{z4 - z3}
1234               .. (lft z4){down}
1235               .. {dir 225}(top z5);
1236         pat := pat
1237                -- reverse pat xscaled -1 shifted (-feta_eps, 0);
1239         % assure symmetry -- it's more important to center the glyph on the
1240         % staff line than centering it between staff lines, so we use
1241         % feta_shift, not feta_space_shift.
1242         h := h + feta_shift;
1244         fill pat shifted (0, feta_shift)
1245              -- reverse pat yscaled -1 shifted (0, -feta_eps)
1246              -- cycle;
1248         % ugh
1249         currentpicture := currentpicture shifted (hround (w / 2), 0);
1251         remember_pic := currentpicture;
1253         draw_staff (-2, 2, 0);
1254 fet_endchar;
1257 draw_shifted_too;
1260 def draw_paren =
1261         save leftindent;
1263         leftindent := .2 staff_space;
1265         set_char_box (0, .5 staff_space# + stafflinethickness#,
1266                       staff_space#, staff_space#);
1268         d := d - feta_shift;
1270         z1 = (leftindent, h);
1271         z2 = (w - stafflinethickness, .5 (h - d));
1272         z3 = (leftindent, -d);
1274         penpos1 (stafflinethickness, 35);
1275         penpos2 (.1 staff_space + stafflinethickness, 0);
1276         penpos3 (stafflinethickness, -35);
1278         fill z2l{down}
1279              .. simple_serif (z3l, z3r, 90)
1280              .. z2r{up}
1281              .. simple_serif (z1r, z1l, 90)
1282              .. z2l{down}
1283              -- cycle;
1284 enddef;
1287 fet_beginchar ("Right Parenthesis", "rightparen");
1288         draw_paren;
1289         penlabels (1, 2, 3);
1291         remember_pic := currentpicture;
1293         draw_staff (-2, 2, 0);
1294 fet_endchar;
1297 draw_shifted_too;
1300 fet_beginchar ("Left Parenthesis", "leftparen");
1301         draw_paren;
1303         currentpicture := currentpicture xscaled -1;
1305         set_char_box (charwd, charbp, chardp, charht);
1306 fet_endchar;
1308 fet_endgroup ("accidentals");