]> git.donarmstrong.com Git - lilypond.git/blob - mf/feta-accidentals.mf
Merge branch 'lilypond/translation' of ssh://thsoft@git.sv.gnu.org/srv/git/lilypond...
[lilypond.git] / mf / feta-accidentals.mf
1 % Feta (not the Font-En-Tja) music font --  Accidentals
2 % This file is part of LilyPond, the GNU music typesetter.
3 %
4 % Copyright (C) 1997--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
5 %
6 %
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.
11 %
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.
16 %
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/>.
19
20
21 %
22 % also show in other configuration wrt staff lines.
23 %
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;
29
30                 draw_staff (-2, 2, 0.5);
31         fet_endchar;
32 fi;
33 enddef;
34
35
36 %
37 % Accidentals from various sources, notably
38 %
39 %   Baerenreiter edition of Schuberts `Auf dem Strom' (sharp, natural)
40 %   F Hofmeister edition of Muellers `Etueden fuer Horn' (double sharp, flat)
41 %
42
43
44 %
45 % Naming for accidentals (including microtonal variants):
46 %
47 %   SHARPBASE[.SLASHES.STEMS]
48 %   FLATBASE[.MODIFIER]
49 %
50 % Examples:
51 %
52 %   sharp.slashslash.stem
53 %   mirroredflat.flat
54 %
55 %
56
57
58 fet_begingroup ("accidentals");
59
60 %
61 % Draw an arrow
62 %
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
67 %
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;
75
76         wwing := 0.26 stemwidth;
77         htip := staff_space * 0.85 + stafflinethickness - wwing;
78
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;
87
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);
92
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;
98
99         z4 = attach shifted ((-0.2 stemwidth, upshift + htip)
100                              transformed flip);
101         z4'= attach shifted (( 0.2 stemwidth, upshift + htip)
102                              transformed flip);
103
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;
113
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);
118
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);
123
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;
137
138         labels (range 0 thru 7, 4', 3a, 3b, 5a, 5b);
139 endgroup;
140 enddef;
141
142 save remember_pic;
143 picture remember_pic;
144
145 save sharp_beamheight;
146 sharp_beamheight# := 0.3 staff_space# + stafflinethickness#;
147
148 %
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.
152 %
153
154 def draw_meta_sharp (expr width, offset) =
155         save beamwidth, beamslope;
156         save ne, nw_dist;
157         pair ne, nw_dist;
158
159         beamwidth := width;
160
161         define_whole_vertical_blacker_pixels (sharp_beamheight);
162
163         clearxy;
164
165         beamslope = sharp_beamheight / beamwidth;
166
167         pickup pencircle scaled 2 blot_diameter;
168
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;
176
177         ne = unitvector (z2 - z1);
178         nw_dist = (ne rotated 90) * blot_diameter;
179
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;
189
190         labels (1, 2, 3, 4);
191 enddef;
192
193
194 def draw_sharp(expr arrowup, arrowdown) =
195         save stem, stemx, stemwidth;
196         save outer_space, interbeam;
197         save stemlength, extendleft, extendright, height, depth;
198
199         stemwidth# := stafflinethickness# + .05 staff_space#;
200         define_whole_blacker_pixels (stemwidth);
201
202         interbeam := 1.05 staff_space_rounded;
203
204         stemlength# := 1.5 staff_space#;
205         define_pixels (stemlength);
206
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#);
221
222         stem := 7 / 16 * w;
223         stemx := hround stem;
224         outer_space := hround ((w - stemx - stemwidth) / 2);
225
226         w := 2 outer_space + stemx + stemwidth;
227         d := d - feta_space_shift;
228
229         draw_meta_sharp (w, -.5 interbeam);
230         draw_meta_sharp (w, -.5 interbeam + vround interbeam);
231
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;
236
237         pickup pencircle scaled stemwidth;
238
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;
245
246         labels (5, 6, 7, 8);
247
248         draw_gridline (z5, z6, stemwidth);
249         draw_gridline (z7, z8, stemwidth);
250
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;
259
260         remember_pic := currentpicture;
261
262         draw_staff (-2, 2, 0);
263 enddef;
264
265
266 fet_beginchar ("Sharp", "sharp");
267         draw_sharp (false, false);
268 fet_endchar;
269
270
271 draw_shifted_too;
272
273
274 fet_beginchar ("Arrowed Sharp (arrow up)", "sharp.arrowup");
275         draw_sharp (true, false);
276 fet_endchar;
277
278
279 draw_shifted_too;
280
281
282 fet_beginchar ("Arrowed Sharp (arrow down)", "sharp.arrowdown");
283         draw_sharp (false, true);
284 fet_endchar;
285
286
287 draw_shifted_too;
288
289
290 fet_beginchar ("Arrowed Sharp (arrows up and down)", "sharp.arrowboth");
291         draw_sharp (true, true);
292 fet_endchar;
293
294
295 draw_shifted_too;
296
297
298 fet_beginchar ("1/2 Sharp", "sharp.slashslash.stem");
299         save stem, stemwidth;
300         save outer_space, interbeam;
301
302         stemwidth# := stafflinethickness# + .05 staff_space#;
303         define_whole_blacker_pixels (stemwidth);
304
305         interbeam := 1.05 staff_space_rounded;
306
307         set_char_box (0, 0.7 staff_space#,
308                       1.5 staff_space#, 1.5 staff_space#);
309
310         stem := 7 / 16 * w;
311         outer_space := hround ((w - stemwidth) / 2);
312
313         w := 2 outer_space + stemwidth;
314         d := d - feta_space_shift;
315
316         draw_meta_sharp (w, -.5 interbeam);
317         draw_meta_sharp (w, -.5 interbeam + vround interbeam);
318
319         pickup pencircle scaled stemwidth;
320
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;
324
325         labels (5, 6);
326
327         draw_gridline (z5, z6, stemwidth);
328
329         remember_pic := currentpicture;
330
331         draw_staff (-2, 2, 0);
332 fet_endchar;
333
334
335 draw_shifted_too;
336
337
338 fet_beginchar ("Sharp (3 beams)", "sharp.slashslashslash.stemstem");
339         save stem, stemx, stemwidth;
340         save outer_space, interbeam;
341         save sharp_beamheight;
342
343         sharp_beamheight# := 0.22 staff_space# + stafflinethickness#;
344
345         stemwidth# := stafflinethickness# + .05 staff_space#;
346         define_whole_blacker_pixels (stemwidth);
347
348         interbeam := 1.2 staff_space_rounded;
349
350         set_char_box (0, 1.1 staff_space#,
351                       1.5 staff_space#, 1.5 staff_space#);
352
353         stem := 7 / 16 * w;
354         stemx := hround stem;
355         outer_space := hround ((w - stemx - stemwidth) / 2);
356
357         w := 2 outer_space + stemx + stemwidth;
358         d := d - feta_space_shift;
359
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);
364
365         pickup pencircle scaled stemwidth;
366
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;
373
374         labels (5, 6, 7, 8);
375
376         draw_gridline (z5, z6, stemwidth);
377         draw_gridline (z7, z8, stemwidth);
378
379         remember_pic := currentpicture;
380
381         draw_staff (-2, 2, 0);
382 fet_endchar;
383
384
385 draw_shifted_too;
386
387
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;
392
393         sharp_beamheight# := 0.22 staff_space# + stafflinethickness#;
394
395         stemwidth# := stafflinethickness# + .05 staff_space#;
396         define_whole_blacker_pixels (stemwidth);
397
398         interbeam := 1.2 staff_space_rounded;
399
400         set_char_box (0, 0.95 staff_space#,
401                       1.3 staff_space#, 1.3 staff_space#);
402
403         stem := 7 / 16 * w;
404         outer_space := hround ((w - stemwidth) / 2);
405
406         w := 2 outer_space + stemwidth;
407         d := d - feta_space_shift;
408
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);
413
414         pickup pencircle scaled stemwidth;
415
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);
420
421         draw_gridline (z5, z6, stemwidth);
422
423         remember_pic := currentpicture;
424
425         draw_staff (-2, 2, 0);
426 fet_endchar;
427
428
429 draw_shifted_too;
430
431
432 fet_beginchar ("3/4 Sharp", "sharp.slashslash.stemstemstem");
433         save stem, stemx, stemwidth;
434         save outer_space, interbeam;
435
436         stemwidth# := stafflinethickness# + .05 staff_space#;
437         define_whole_blacker_pixels (stemwidth);
438
439         interbeam := 1.05 staff_space_rounded;
440
441         set_char_box (0, 1.6 staff_space#,
442                       1.5 staff_space#, 1.5 staff_space#);
443
444         stem := 9 / 32 * w;
445         stemx := hround stem;
446         outer_space := hround ((w - 2 stemx - stemwidth) / 2);
447
448         w := 2 outer_space + 2 stemx + stemwidth;
449         d := d - feta_space_shift;
450
451         draw_meta_sharp (w, -.5 interbeam);
452         draw_meta_sharp (w, -.5 interbeam + vround interbeam);
453
454         pickup pencircle scaled stemwidth;
455
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];
465
466         labels (5, 6, 7, 8, 9, 10);
467
468         draw_gridline (z5, z6, stemwidth);
469         draw_gridline (z7, z8, stemwidth);
470         draw_gridline (z9, z10, stemwidth);
471
472         remember_pic := currentpicture;
473
474         draw_staff (-2, 2, 0);
475 fet_endchar;
476
477
478 draw_shifted_too;
479
480
481 %
482 % The stems of the natural are brushed (at least, in Barenreiter SCS)
483 %
484
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;
492
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);
496
497         stemlength# = 1.5 staff_space#;
498         define_pixels (stemlength);
499
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);
513
514         set_char_box (extendleft#, 2/3 staff_space#, depth#, height#);
515
516         d := d - feta_space_shift;
517
518         pickup pencircle scaled stemwidth;
519
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;
529
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);
537
538         x2r = w;
539         x4l = 0;
540         x3 = x3' = x2;
541         x1 = x1' = x4;
542
543         y1 = y1' = stemlength;
544         y3 = y3' = -stemlength;
545         top y2 = vround (staff_space - 3/2 stafflinethickness);
546         y4 = -y2 + feta_space_shift;
547
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;
554
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;
561
562         ne = (x2 - x4, stafflinethickness);
563
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;
573
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;
583
584         fill z11
585              -- z12
586              -- z13
587              -- z14
588              -- cycle;
589         fill z21
590              -- z22
591              -- z23
592              -- z24
593              -- cycle;
594
595         penlabels (1, 1', 2, 3, 3', 4);
596         labels (11, 11', 12, 13, 14, 21, 21', 22, 23, 24);
597
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;
607
608         remember_pic := currentpicture;
609
610         draw_staff (-2, 2, 0);
611 enddef;
612
613
614 fet_beginchar ("Natural", "natural");
615         draw_natural (false, false);
616 fet_endchar;
617
618
619 draw_shifted_too;
620
621
622 fet_beginchar ("Arrowed Natural (arrow up)", "natural.arrowup");
623         draw_natural (true, false);
624 fet_endchar;
625
626
627 draw_shifted_too;
628
629
630 fet_beginchar ("Arrowed Natural (arrow down)", "natural.arrowdown");
631         draw_natural (false, true);
632 fet_endchar;
633
634
635 draw_shifted_too;
636
637
638 fet_beginchar ("Arrowed Natural (arrows up and down)", "natural.arrowboth");
639         draw_natural (true, true);
640 fet_endchar;
641
642
643 draw_shifted_too;
644
645
646 %
647 % Dedicated to my mom.    (3/10/97)
648 %
649 % Mamma, ik hou van je; kom je alsjeblieft terug?
650 %    -- HW
651 %
652 %
653 % TODO: remove crook_fatness
654 % TODO: document, simplify!
655 %
656
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;
667
668         clearxy;
669
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;
688
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);
698
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;
705
706         center = (xcenter, 0);
707
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);
718
719         penpos1 (top_stem_thick, 0);
720         penpos16 (top_stem_thick_orig, 0);
721         penpos2 (bottom_stem_thick, 0);
722
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;
729
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;
736
737         z10 = whatever [z2r, z16r] + (smaller_hole, 0);
738         y10 = -1/10 staff_space;
739         x10 := hceiling x10;
740
741         x11 = xcenter + bottom_overshoot / 3;
742         y11 = -vround (.5 (staff_space + stafflinethickness)
743                        + bottom_overshoot);
744
745         x2a = 0.2[x2r, x7];
746         y2a = 1.5[y2, y11];
747
748         penpos4 (whatever, 53);
749
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;
756
757         penpos5 (crook_fatness, -175);
758
759         bot_crook_dir = unitvector ((x5l, 0) - z11);
760         z8 = z11 + whatever * bot_crook_dir;
761         y8 = -staff_space / 2;
762
763         z7 = z8
764              + whatever * bot_crook_dir
765              + crook_thinness * (bot_crook_dir rotated 90);
766         x7 = .1 [x3r, x8];
767
768         unfill z3r{z3r - z10}
769                .. z4r{right}
770                .. z5r{down}
771                .. z7{-bot_crook_dir}
772                & z7
773                .. z10{z3r - z10}
774                -- cycle;
775
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;
793
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;
803
804
805 def draw_arrowed_meta_flat (expr xcenter, width, crook_fatness,
806                                  arrowup, arrowdown) =
807         save depth, height, extendleft;
808
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;
820
821         set_char_box (extendleft#, width, depth#, height#);
822         draw_meta_flat(xcenter, w, crook_fatness, arrowup, arrowdown);
823 enddef;
824
825 %
826 % unfortunately, 600dpi is not enough to show the brush of the stem.
827 %
828
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);
833
834         remember_pic := currentpicture;
835
836         draw_staff (-2, 2, 0);
837 fet_endchar;
838
839
840 draw_shifted_too;
841
842
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);
847
848         remember_pic := currentpicture;
849
850         draw_staff (-2, 2, 0);
851 fet_endchar;
852
853
854 draw_shifted_too;
855
856
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);
861
862         remember_pic := currentpicture;
863
864         draw_staff (-2, 2, 0);
865 fet_endchar;
866
867
868 draw_shifted_too;
869
870
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);
875
876         remember_pic := currentpicture;
877
878         draw_staff (-2, 2, 0);
879 fet_endchar;
880
881
882 draw_shifted_too;
883
884
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#);
888
889         draw_meta_flat (0, w, 0.31 staff_space, false, false);
890
891         clearxy;
892
893         save slope, slash_width;
894         slope = 0.5;
895         slash_width = w;
896
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);
902
903         z14 = z12 - .75 stafflinethickness * unitvector (z13 - z12);
904         z15 = z13 + .75 stafflinethickness * unitvector (z13 - z12);
905
906         fill z13r
907              .. z15
908              .. z13l
909              -- z12l
910              .. z14
911              .. z12r
912              -- z13r
913              .. cycle;
914
915         penlabels (12, 13);
916         labels (14, 15);
917
918         remember_pic := currentpicture;
919
920         draw_staff (-2, 2, 0);
921 fet_endchar;
922
923
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#);
927
928         draw_meta_flat (0, w, 0.31 staff_space, false, false);
929
930         clearxy;
931
932         save slope, slash_width;
933         slope = 0.5;
934         slash_width = w;
935
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);
941
942         z14 = z12 - .75 stafflinethickness * unitvector (z13 - z12);
943         z15 = z13 + .75 stafflinethickness * unitvector (z13 - z12);
944
945         fill z13r
946              .. z15
947              .. z13l
948              -- z12l
949              .. z14
950              .. z12r
951              -- z13r
952              .. cycle;
953
954         penlabels (12, 13);
955         labels (14, 15);
956
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);
962
963         z24 = z22 - .75 stafflinethickness * unitvector (z23 - z22);
964         z25 = z23 + .75 stafflinethickness * unitvector (z23 - z22);
965
966         fill z23r
967              .. z25
968              .. z23l
969              -- z22l
970              .. z24
971              .. z22r
972              -- z23r
973              .. cycle;
974
975         penlabels (22, 23);
976         labels (24, 25);
977
978         remember_pic := currentpicture;
979
980         draw_staff (-2, 2, 0);
981 fet_endchar;
982
983
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#);
987
988         % This is a modified version of `draw_meta_flat'.
989
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;
1000
1001         clearxy;
1002
1003         wid = w / 2;
1004
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;
1020
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);
1024
1025         if odd (top_stem_thick - bottom_stem_thick):
1026                 top_stem_thick := top_stem_thick - 1;
1027         fi;
1028
1029         center = (0, 0);
1030
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;
1035
1036         penpos1 (top_stem_thick, 0);
1037         penpos2 (bottom_stem_thick, 0);
1038
1039         y3l = vfloor ((staff_space - stafflinethickness) / 2);
1040         z3l = whatever [z2r, z1r];
1041         z3r = .3 [z2r, z1r] + (smaller_hole, 0);
1042         x3r := hceiling x3r;
1043
1044         z10 = whatever [z2r, z1r] + (smaller_hole, 0);
1045         y10 = -1/10 staff_space;
1046         x10 := hceiling x10;
1047
1048         x11 = bottom_overshoot / 3;
1049         y11 = -vround (.5 (staff_space + stafflinethickness)
1050                        + bottom_overshoot);
1051
1052         penpos4 (whatever, 53);
1053
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;
1060
1061         penpos5 (crook_fatness, -175);
1062
1063         bot_crook_dir = unitvector ((x5l, 0) - z11);
1064         z8 = z11 + whatever * bot_crook_dir;
1065         y8 = -staff_space / 2;
1066
1067         z7 = z8
1068              + whatever * bot_crook_dir
1069              + crook_thinness * (bot_crook_dir rotated 90);
1070         x7 = .1 [x3r, x8];
1071
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;
1081
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;
1091
1092         currentpicture := currentpicture shifted (w/2, 0);
1093
1094         remember_pic := currentpicture;
1095
1096         draw_staff (-2, 2, 0);
1097 fet_endchar;
1098
1099
1100 draw_shifted_too;
1101
1102
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#);
1106
1107         draw_meta_flat (0, w, 0.31 staff_space, false, false);
1108         currentpicture := currentpicture xscaled -1 shifted (w - b, 0);
1109 fet_endchar;
1110
1111
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#);
1115
1116         draw_meta_flat (0, w, 0.31 staff_space, false, false);
1117
1118         clearxy;
1119
1120         save slope, slash_width;
1121         slope = 0.5;
1122         slash_width = w;
1123
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);
1129
1130         z14 = z12 - .75 stafflinethickness * unitvector (z13 - z12);
1131         z15 = z13 + .75 stafflinethickness * unitvector (z13 - z12);
1132
1133         fill z13r
1134              .. z15
1135              .. z13l
1136              -- z12l
1137              .. z14
1138              .. z12r
1139              -- z13r
1140              .. cycle;
1141
1142         currentpicture := currentpicture xscaled -1 shifted (w - b, 0);
1143
1144         labels (1, 2, 3);
1145 fet_endchar;
1146
1147
1148 fet_beginchar ("Double Flat", "flatflat");
1149         save left_wid, overlap, right_wid;
1150
1151         left_wid = .7;
1152         right_wid = .8;
1153         overlap = .05;
1154
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;
1164
1165
1166 fet_beginchar ("3/4 Flat", "flatflat.slash");
1167         save left_wid, overlap, right_wid;
1168
1169         left_wid = .7;
1170         right_wid = .8;
1171         overlap = .05;
1172
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);
1181
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;
1186
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);
1191
1192         z14 = z12 - stafflinethickness * unitvector (z13 - z12);
1193         z15 = z13 + stafflinethickness * unitvector (z13 - z12);
1194
1195         fill z13r
1196              .. z15
1197              .. z13l
1198              -- z12l
1199              .. z14
1200              .. z12r
1201              -- z13r
1202              .. cycle;
1203
1204         penlabels (12, 13);
1205         labels (14, 15);
1206
1207         remember_pic := currentpicture;
1208
1209         draw_staff (-2, 2, 0);
1210 fet_endchar;
1211
1212
1213 draw_shifted_too;
1214
1215
1216 fet_beginchar ("Double Sharp", "doublesharp");
1217         save klaverblad, klaversteel;
1218         save pat;
1219         path pat;
1220
1221         klaversteel = 1/15 staff_space;
1222         klaverblad = .4 staff_space - .5 stafflinethickness;
1223
1224         set_char_box (0, staff_space#, .5 staff_space#, .5 staff_space#);
1225
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));
1231
1232         labels (1, 2, 3, 4, 5);
1233
1234         pickup pencircle scaled blot_diameter;
1235
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;
1240
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);
1251
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;
1256
1257         fill pat shifted (0, feta_shift)
1258              -- reverse pat yscaled -1 shifted (0, -feta_eps)
1259              -- cycle;
1260
1261         % ugh
1262         currentpicture := currentpicture shifted (hround (w / 2), 0);
1263
1264         remember_pic := currentpicture;
1265
1266         draw_staff (-2, 2, 0);
1267 fet_endchar;
1268
1269
1270 draw_shifted_too;
1271
1272
1273 def draw_paren =
1274         save leftindent;
1275
1276         leftindent := .2 staff_space;
1277
1278         set_char_box (0, .5 staff_space# + stafflinethickness#,
1279                       staff_space#, staff_space#);
1280
1281         d := d - feta_shift;
1282
1283         z1 = (leftindent, h);
1284         z2 = (w - stafflinethickness, .5 (h - d));
1285         z3 = (leftindent, -d);
1286
1287         penpos1 (stafflinethickness, 35);
1288         penpos2 (.1 staff_space + stafflinethickness, 0);
1289         penpos3 (stafflinethickness, -35);
1290
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;
1298
1299
1300 fet_beginchar ("Right Parenthesis", "rightparen");
1301         draw_paren;
1302         penlabels (1, 2, 3);
1303
1304         remember_pic := currentpicture;
1305
1306         draw_staff (-2, 2, 0);
1307 fet_endchar;
1308
1309
1310 draw_shifted_too;
1311
1312
1313 fet_beginchar ("Left Parenthesis", "leftparen");
1314         draw_paren;
1315
1316         currentpicture := currentpicture xscaled -1;
1317
1318         set_char_box (charwd, charbp, chardp, charht);
1319 fet_endchar;
1320
1321 fet_endgroup ("accidentals");