2 % feta-toevallig.mf -- implement Accidentals
4 % source file of the Feta (Font-En-Tja) music font
6 % (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
11 % Accidentals from various sources, notably
13 % Baerenreiter edition of Schuberts `Auf dem Strom' (sharp, natural)
14 % F Hofmeister edition of Muellers `Etueden fuer Horn' (double sharp, flat)
18 fet_begingroup ("accidentals");
26 % The beams of most sharps have horizontal endings (as if drawn with
27 % a square pen). [Wanske] does not mention this, so we'll just ignore
31 def draw_meta_sharp (expr width, offset) =
32 save beamheight, beamwidth, beamslope;
38 beamheight# := 0.3 staff_space# + stafflinethickness#;
39 define_whole_vertical_blacker_pixels (beamheight);
43 beamslope = beamheight / beamwidth;
45 pickup pencircle scaled 2 blot_diameter;
47 rt x2 - lft x1 = beamwidth;
49 .5 [z1, z3] = (.5 w, offset);
51 top y2 - bot y3 = beamheight;
53 top y1 - bot y4 = beamheight;
55 ne = unitvector (z2 - z1);
56 nw_dist = (ne rotated 90) * blot_diameter;
59 ... (z1 + nw_dist){ne}
63 ... (z3 - nw_dist){-ne}
64 -- (z4 - nw_dist){-ne}
72 fet_beginchar ("Sharp", "2");
73 save stem, stemx, stemwidth;
74 save outer_space, interbeam;
76 stemwidth# := stafflinethickness# + .05 staff_space#;
77 define_whole_blacker_pixels (stemwidth);
79 interbeam := 1.05 staff_space_rounded;
81 set_char_box (0, 1.1 staff_space#,
82 1.5 staff_space#, 1.5 staff_space#);
86 outer_space := hround ((w - stemx - stemwidth) / 2);
88 w := 2 outer_space + stemx + stemwidth;
89 d := d - feta_space_shift;
91 draw_meta_sharp (w, -.5 interbeam);
92 draw_meta_sharp (w, -.5 interbeam + vround interbeam);
94 pickup pencircle scaled stemwidth;
96 lft x5 = lft x6 = outer_space;
97 lft x7 = lft x8 = outer_space + stemx;
99 top y6 = vround (1.5 staff_space - stem * beamslope);
100 bot y7 = -top y6 + feta_space_shift;
105 draw_gridline (z5, z6, stemwidth);
106 draw_gridline (z7, z8, stemwidth);
108 remember_pic := currentpicture;
110 draw_staff (-2, 2, 0);
115 fet_beginchar ("Sharp", "2");
117 set_char_box (0, 1.1 staff_space#,
118 1.5 staff_space#, 1.5 staff_space#);
120 currentpicture := remember_pic;
122 draw_staff (-2, 2, 0.5);
127 fet_beginchar ("1/2 Sharp", "1");
128 save stem, stemwidth;
129 save outer_space, interbeam;
131 stemwidth# := stafflinethickness# + .05 staff_space#;
132 define_whole_blacker_pixels (stemwidth);
134 interbeam := 1.05 staff_space_rounded;
136 set_char_box (0, 0.7 staff_space#,
137 1.5 staff_space#, 1.5 staff_space#);
140 outer_space := hround ((w - stemwidth) / 2);
142 w := 2 outer_space + stemwidth;
143 d := d - feta_space_shift;
145 draw_meta_sharp (w, -.5 interbeam);
146 draw_meta_sharp (w, -.5 interbeam + vround interbeam);
148 pickup pencircle scaled stemwidth;
150 lft x5 = lft x6 = outer_space;
151 top y6 = vround (1.5 staff_space - .5 stem);
152 bot y5 = -top y6 + feta_space_shift;
156 draw_gridline (z5, z6, stemwidth);
158 remember_pic := currentpicture;
160 draw_staff (-2, 2, 0);
165 fet_beginchar ("1/2 Sharp", "1");
167 set_char_box (0, 0.7 staff_space#,
168 1.5 staff_space#, 1.5 staff_space#);
170 currentpicture := remember_pic;
172 draw_staff (-2, 2, 0.5);
177 fet_beginchar ("3/4 Sharp", "3");
178 save stem, stemx, stemwidth;
179 save outer_space, interbeam;
181 stemwidth# := stafflinethickness# + .05 staff_space#;
182 define_whole_blacker_pixels (stemwidth);
184 interbeam := 1.05 staff_space_rounded;
186 set_char_box (0, 1.6 staff_space#,
187 1.5 staff_space#, 1.5 staff_space#);
190 stemx := hround stem;
191 outer_space := hround ((w - 2 stemx - stemwidth) / 2);
193 w := 2 outer_space + 2 stemx + stemwidth;
194 d := d - feta_space_shift;
196 draw_meta_sharp (w, -.5 interbeam);
197 draw_meta_sharp (w, -.5 interbeam + vround interbeam);
199 pickup pencircle scaled stemwidth;
201 lft x5 = lft x6 = outer_space;
202 lft x7 = lft x8 = outer_space + stemx;
203 lft x9 = lft x10 = outer_space + 2 stemx;
205 top y6 = vround (1.5 staff_space - 2 stem * beamslope);
206 bot y9 = -top y6 + feta_space_shift;
211 labels (5, 6, 7, 8, 9, 10);
213 draw_gridline (z5, z6, stemwidth);
214 draw_gridline (z7, z8, stemwidth);
215 draw_gridline (z9, z10, stemwidth);
217 remember_pic := currentpicture;
219 draw_staff (-2, 2, 0);
224 fet_beginchar ("3/4 Sharp", "3");
226 set_char_box (0, 1.6 staff_space#,
227 1.5 staff_space#, 1.5 staff_space#);
229 currentpicture := remember_pic;
231 draw_staff (-2, 2, 0.5);
237 % The stems of the natural are brushed (at least, in Barenreiter SCS)
240 fet_beginchar ("Natural", "0");
241 save stemwidth, top_stem_thick;
242 save ne, pat_top, pat_bottom;
244 path pat_top, pat_bottom;
246 top_stem_thick# = stafflinethickness# + .10 staff_space#;
247 stemwidth# = 0.09 staff_space# + .5 stafflinethickness#;
248 define_whole_blacker_pixels (top_stem_thick, stemwidth);
250 set_char_box (0, 2/3 staff_space#,
251 1.5 staff_space#, 1.5 staff_space#);
253 d := d - feta_space_shift;
255 pickup pencircle scaled stemwidth;
257 penpos1 (top_stem_thick, 0);
258 penpos3 (top_stem_thick, 0);
259 penpos2 (stemwidth, 0);
260 penpos4 (stemwidth, 0);
269 top y2 = vround (staff_space - 3/2 stafflinethickness);
270 y4 = -y2 + feta_space_shift;
272 pat_bottom := z4r{z4r - z1r}
275 fill simple_serif (z1l, z1r, -30)
279 pat_top := z2r{z2r - z3r}
282 fill simple_serif (z3l, z3r, 30)
286 ne = (x2 - x4, stafflinethickness);
288 z11' = z3l + whatever * (z2l - z3l);
289 y11' = vround (.5 (staff_space - stafflinethickness));
290 z11 = z11' + whatever * ne;
292 z12 = directionpoint -ne of pat_top;
293 z13 = z12 + whatever * ne;
295 z14 = z11 + whatever * ne;
298 z21' = z4r + whatever * (z1r - z4r);
299 y21' = -y11' + feta_space_shift;
300 z21 = z21' + whatever * ne;
302 z22 = directionpoint -ne of pat_bottom;
303 z23 = z22 + whatever * ne;
305 z24 = z21 + whatever * ne;
319 penlabels (1, 2, 3, 4);
320 labels (11, 11', 12, 13, 14, 21, 21', 22, 23, 24);
322 remember_pic := currentpicture;
324 draw_staff (-2, 2, 0);
329 fet_beginchar ("Natural", "0");
330 set_char_box (0, 2/3 staff_space#,
331 1.5 staff_space#, 1.5 staff_space#);
333 currentpicture := remember_pic;
335 draw_staff (-2, 2, 0.5);
341 % Dedicated to my mom. (3/10/97)
343 % Mamma, ik hou van je; kom je alsjeblieft terug?
347 % TODO: remove crook_fatness
348 % TODO: document, simplify!
351 def draw_meta_flat (expr xcenter, w, crook_fatness) =
353 save bottom_overshoot, bot_crook_dir;
354 save top_stem_thick, bottom_stem_thick, hair, smaller_hole;
355 save top_crook_thinness;
358 pair center, bot_crook_dir;
363 % the stem shouldn't reach the top staff line.
364 %% TODO: should take from height.
366 % TODO: parameterize this
368 if w >= 0.75 staff_space:
369 smaller_hole = 0.35 stafflinethickness;
373 clearing = 1.7 stafflinethickness;
374 crook_thinness = .7 stafflinethickness + .06 staff_space;
375 top_crook_thinness = 1 stafflinethickness + .065 staff_space;
376 bottom_overshoot = stafflinethickness;
378 bottom_stem_thick# = 0.06 staff_space# + 0.6 stafflinethickness#;
379 top_stem_thick# = 0.1 staff_space# + 1.2 stafflinethickness#;
380 define_whole_blacker_pixels (bottom_stem_thick, top_stem_thick);
382 if odd (top_stem_thick - bottom_stem_thick):
383 top_stem_thick := top_stem_thick - 1;
386 center = (xcenter, 0);
388 x1l = hround (xcenter - .5 top_stem_thick);
389 y1 = vround (2 staff_space - clearing);
390 x2l = hround (xcenter - .5 bottom_stem_thick);
391 y2 = -.5 staff_space - .5 stafflinethickness;
393 penpos1 (top_stem_thick, 0);
394 penpos2 (bottom_stem_thick, 0);
396 y3l = vfloor ((staff_space - stafflinethickness) / 2);
397 z3l = whatever [z2r, z1r];
398 z3r = .3 [z2r, z1r] + (smaller_hole, 0);
401 % we insert z3l to get better conversion with mf2pt1
402 fill simple_serif (z1r, z1l, 30)
408 z10 = whatever [z2r, z1r] + (smaller_hole, 0);
409 y10 = -1/10 staff_space;
412 x11 = xcenter + bottom_overshoot / 3;
413 y11 = -vround (.5 (staff_space + stafflinethickness)
416 penpos4 (whatever, 53);
418 y4l - y4r = top_crook_thinness;
419 y5r = .15 staff_space;
420 x5l = hround (w + xcenter);
421 y4 = staff_space / 2;
422 x4r = .45 [x5r, x3r];
425 penpos5 (crook_fatness, -175);
427 bot_crook_dir = unitvector ((x5l, 0) - z11);
428 z8 = z11 + whatever * bot_crook_dir;
429 y8 = -staff_space / 2;
432 + whatever * bot_crook_dir
433 + crook_thinness * (bot_crook_dir rotated 90);
436 unfill z3r{z3r - z10}
439 .. z7{-bot_crook_dir}
455 % unfortunately, 600dpi is not enough to show the brush of the stem.
458 fet_beginchar ("Flat", "-2");
459 set_char_box (1.2 stafflinethickness#, .8 staff_space#,
460 0.6 staff_space#, 1.9 staff_space#);
462 draw_meta_flat (0, w, 0.31 staff_space);
463 penlabels (range 0 thru 11);
465 remember_pic := currentpicture;
467 draw_staff (-2, 2, 0);
472 fet_beginchar ("Flat", "-2");
473 set_char_box (1.2 stafflinethickness#, .8 staff_space#,
474 0.6 staff_space#, 1.9 staff_space#);
476 currentpicture := remember_pic;
478 draw_staff (-2, 2, 0.5);
483 fet_beginchar ("Semi flat", "-1");
484 set_char_box (1.2 stafflinethickness#, .8 staff_space#,
485 0.6 staff_space#, 1.9 staff_space#);
487 draw_meta_flat (0, w, 0.31 staff_space);
488 currentpicture := currentpicture xscaled -1 shifted (w - b, 0);
492 fet_beginchar ("Double Flat", "-4");
493 save left_wid, overlap, right_wid;
499 set_char_box (1.2 stafflinethickness#,
500 (left_wid + right_wid - overlap) * staff_space#,
501 .6 staff_space#, 1.9 staff_space#);
502 draw_meta_flat (0, left_wid * staff_space, 1/3 staff_space);
503 draw_meta_flat (round ((left_wid - overlap) * staff_space),
504 right_wid * staff_space, 0.33 staff_space);
508 fet_beginchar ("3/4 Flat", "-3");
509 save left_wid, overlap, right_wid;
515 set_char_box (1.2 stafflinethickness#,
516 (left_wid + right_wid - overlap) * staff_space#,
517 .6 staff_space#, 1.9 staff_space#);
518 draw_meta_flat (0, left_wid * staff_space, 1/3 staff_space);
519 draw_meta_flat (round ((left_wid - overlap) * staff_space),
520 right_wid * staff_space, 0.33 staff_space);
522 %% maybe we should clip part of the stems?
523 %% or make the 1st flat smaller?
525 pickup pencircle scaled 2 stafflinethickness;
527 z12 = round (-.25 w - b, .55 staff_space) + feta_offset;
528 z13 = round (.75 w, 1.45 staff_space) + feta_offset;
529 penpos12 (2 stafflinethickness, angle (z13 - z12) - 90);
530 penpos13 (2 stafflinethickness, angle (z13 - z12) - 90);
532 z14 = z12 - stafflinethickness * unitvector (z13 - z12);
533 z15 = z13 + stafflinethickness * unitvector (z13 - z12);
547 remember_pic := currentpicture;
549 draw_staff (-2, 2, 0);
554 fet_beginchar ("3/4 Flat", "-3");
555 save left_wid, overlap, right_wid;
561 set_char_box (1.2 stafflinethickness#,
562 (left_wid + right_wid - overlap) * staff_space#,
563 .6 staff_space#, 1.9 staff_space#);
565 currentpicture := remember_pic;
567 draw_staff (-2, 2, 0.5);
572 fet_beginchar ("Double Sharp", "4");
573 save klaverblad, klaversteel;
577 klaversteel = 1/15 staff_space;
578 klaverblad = .4 staff_space - .5 stafflinethickness;
580 set_char_box (0, staff_space#, .5 staff_space#, .5 staff_space#);
582 z1 = (klaversteel, 0);
583 z2 = (w / 2 - klaverblad / 10, h - klaverblad);
585 z4 = z2 reflectedabout ((0, 0), (1, 1));
586 z5 = z1 reflectedabout ((0, 0), (1, 1));
588 labels (1, 2, 3, 4, 5);
590 pickup pencircle scaled blot_diameter;
592 x2 := hfloor (rt x2) - blot_diameter / 2;
593 x3 := hfloor (rt x3) - blot_diameter / 2;
594 y3 := vfloor (top y3) - blot_diameter / 2;
595 y4 := vfloor (top y4) - blot_diameter / 2;
604 .. {dir 225}(top z5);
606 -- reverse pat xscaled -1 shifted (-feta_eps, 0);
608 % assure symmetry -- it's more important to center the glyph on the
609 % staff line than centering it between staff lines, so we use
610 % feta_shift, not feta_space_shift.
613 fill pat shifted (0, feta_shift)
614 -- reverse pat yscaled -1 shifted (0, -feta_eps)
618 currentpicture := currentpicture shifted (hround (w / 2), 0);
620 remember_pic := currentpicture;
622 draw_staff (-2, 2, 0);
627 fet_beginchar ("Double Sharp", "4");
628 set_char_box (0, staff_space#,
629 .5 staff_space#, .5 staff_space#);
631 currentpicture := remember_pic;
633 draw_staff (-2, 2, 0.5);
641 leftindent := .2 staff_space;
643 set_char_box (0, .5 staff_space# + stafflinethickness#,
644 staff_space#, staff_space#);
648 z1 = (leftindent, h);
649 z2 = (w - stafflinethickness, .5 (h - d));
650 z3 = (leftindent, -d);
652 penpos1 (stafflinethickness, 35);
653 penpos2 (.1 staff_space + stafflinethickness, 0);
654 penpos3 (stafflinethickness, -35);
657 .. simple_serif (z3l, z3r, 90)
659 .. simple_serif (z1r, z1l, 90)
665 fet_beginchar ("Right Parenthesis", "rightparen");
669 remember_pic := currentpicture;
671 draw_staff (-2, 2, 0);
676 fet_beginchar ("Right Parenthesis", "rightparen");
680 remember_pic := currentpicture;
682 draw_staff (-2, 2, 0.5);
687 fet_beginchar ("Left Parenthesis", "leftparen");
690 currentpicture := currentpicture xscaled -1;
692 set_char_box (charwd, charbp, chardp, charht);
696 fet_endgroup ("accidentals");