2 % feta-toevallig.mf -- implement Accidentals
4 % source file of the Feta (Font-En-Tja) music font
6 % (c) 1997--2004 Han-Wen Nienhuys <hanwen@cs.uu.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");
242 save interbeam, interstem;
243 save beamheight, beamwidth;
244 save stemwidth, top_stem_thick;
246 beamheight# = 0.35 staff_space# + .5 stafflinethickness#;
247 top_stem_thick# = stafflinethickness# + .09 staff_space#;
248 stemwidth# = 0.08 staff_space# + .5 stafflinethickness#;
249 define_whole_vertical_blacker_pixels (beamheight);
250 define_whole_blacker_pixels (top_stem_thick, stemwidth);
252 set_char_box (0, 2/3 staff_space#,
253 1.5 staff_space#, 1.5 staff_space#);
255 interstem + stemwidth = w;
257 z2 - z1 = (interstem, slope * interstem);
258 xpart .5 [z2, z1] = w / 2;
260 d := d - feta_space_shift;
262 pickup penrazor scaled beamheight rotated 90;
263 top y2 = vround (staff_space - 3/2 stafflinethickness);
264 slope = stafflinethickness / interstem;
272 bot y1' = -d + (h - top y2);
282 pickup pencircle scaled stemwidth;
286 penpos3 (top_stem_thick, 0);
287 penpos5 (top_stem_thick, 0);
288 penpos4 (stemwidth, 0);
289 penpos6 (stemwidth, 0);
295 y6 = -y4 + feta_space_shift;
298 fill simple_serif (z3l, z3r, -30)
303 fill simple_serif (z5l, z5r, 30)
309 penlabels (3, 4, 5, 6);
310 labels (1, 1', 2, 2');
312 remember_pic := currentpicture;
314 draw_staff (-2, 2, 0);
319 fet_beginchar ("Natural", "0");
320 set_char_box (0, 2/3 staff_space#,
321 1.5 staff_space#, 1.5 staff_space#);
323 currentpicture := remember_pic;
325 draw_staff (-2, 2, 0.5);
331 % Dedicated to my mom. (3/10/97)
333 % Mamma, ik hou van je; kom je alsjeblieft terug?
337 % TODO: remove crook_fatness
338 % TODO: document, simplify!
341 def draw_meta_flat (expr xcenter, w, crook_fatness) =
343 save bottom_overshoot, bot_crook_dir;
344 save top_stem_thick, bottom_stem_thick, hair, smaller_hole;
345 save top_crook_thinness;
348 pair center, bot_crook_dir;
353 % the stem shouldn't reach the top staff line.
354 %% TODO: should take from height.
356 % TODO: parameterize this
358 if w >= 0.75 staff_space:
359 smaller_hole = 0.35 stafflinethickness;
363 clearing = 1.7 stafflinethickness;
364 crook_thinness = .7 stafflinethickness + .06 staff_space;
365 top_crook_thinness = 1 stafflinethickness + .065 staff_space;
366 bottom_overshoot = stafflinethickness;
368 bottom_stem_thick# = 0.06 staff_space# + 0.6 stafflinethickness#;
369 top_stem_thick# = 0.1 staff_space# + 1.2 stafflinethickness#;
370 define_whole_blacker_pixels (bottom_stem_thick, top_stem_thick);
372 if odd (top_stem_thick - bottom_stem_thick):
373 top_stem_thick := top_stem_thick - 1;
376 center = (xcenter, 0);
378 x1l = hround (xcenter - .5 top_stem_thick);
379 y1 = vround (2 staff_space - clearing);
380 x2l = hround (xcenter - .5 bottom_stem_thick);
381 y2 = -.5 staff_space - .5 stafflinethickness;
383 penpos1 (top_stem_thick, 0);
384 penpos2 (bottom_stem_thick, 0);
386 y3l = vfloor ((staff_space - stafflinethickness) / 2);
387 z3l = whatever [z2r, z1r];
388 z3r = .3 [z2r, z1r] + (smaller_hole, 0);
391 % we insert z3l to get better conversion with mf2pt1
392 fill simple_serif (z1r, z1l, 30)
398 z10 = whatever [z2r, z1r] + (smaller_hole, 0);
399 y10 = -1/10 staff_space;
402 x11 = xcenter + bottom_overshoot / 3;
403 y11 = -vround (.5 (staff_space + stafflinethickness)
406 penpos4 (whatever, 53);
408 y4l - y4r = top_crook_thinness;
409 y5r = .15 staff_space;
410 x5l = hround (w + xcenter);
411 y4 = staff_space / 2;
412 x4r = .45 [x5r, x3r];
415 penpos5 (crook_fatness, -175);
417 bot_crook_dir = unitvector ((x5l, 0) - z11);
418 z8 = z11 + whatever * bot_crook_dir;
419 y8 = -staff_space / 2;
422 + whatever * bot_crook_dir
423 + crook_thinness * (bot_crook_dir rotated 90);
426 unfill z3r{z3r - z10}
429 .. z7{-bot_crook_dir}
445 % unfortunately, 600dpi is not enough to show the brush of the stem.
448 fet_beginchar ("Flat", "-2");
449 set_char_box (1.2 stafflinethickness#, .8 staff_space#,
450 0.6 staff_space#, 1.9 staff_space#);
452 draw_meta_flat (0, w, 0.31 staff_space);
453 penlabels (range 0 thru 11);
455 remember_pic := currentpicture;
457 draw_staff (-2, 2, 0);
462 fet_beginchar ("Flat", "-2");
463 set_char_box (1.2 stafflinethickness#, .8 staff_space#,
464 0.6 staff_space#, 1.9 staff_space#);
466 currentpicture := remember_pic;
468 draw_staff (-2, 2, 0.5);
473 fet_beginchar ("Semi flat", "-1");
474 set_char_box (1.2 stafflinethickness#, .8 staff_space#,
475 0.6 staff_space#, 1.9 staff_space#);
477 draw_meta_flat (0, w, 0.31 staff_space);
478 currentpicture := currentpicture xscaled -1 shifted (w - b, 0);
482 fet_beginchar ("Double Flat", "-4");
483 save left_wid, overlap, right_wid;
489 set_char_box (1.2 stafflinethickness#,
490 (left_wid + right_wid - overlap) * staff_space#,
491 .6 staff_space#, 1.9 staff_space#);
492 draw_meta_flat (0, left_wid * staff_space, 1/3 staff_space);
493 draw_meta_flat (round ((left_wid - overlap) * staff_space),
494 right_wid * staff_space, 0.33 staff_space);
498 fet_beginchar ("3/4 Flat", "-3");
499 save left_wid, overlap, right_wid;
505 set_char_box (1.2 stafflinethickness#,
506 (left_wid + right_wid - overlap) * staff_space#,
507 .6 staff_space#, 1.9 staff_space#);
508 draw_meta_flat (0, left_wid * staff_space, 1/3 staff_space);
509 draw_meta_flat (round ((left_wid - overlap) * staff_space),
510 right_wid * staff_space, 0.33 staff_space);
512 %% maybe we should clip part of the stems?
513 %% or make the 1st flat smaller?
515 pickup pencircle scaled 2 stafflinethickness;
517 z12 = round (-.25 w - b, .55 staff_space) + feta_offset;
518 z13 = round (.75 w, 1.45 staff_space) + feta_offset;
519 penpos12 (2 stafflinethickness, angle (z13 - z12) - 90);
520 penpos13 (2 stafflinethickness, angle (z13 - z12) - 90);
522 z14 = z12 - stafflinethickness * unitvector (z13 - z12);
523 z15 = z13 + stafflinethickness * unitvector (z13 - z12);
537 remember_pic := currentpicture;
539 draw_staff (-2, 2, 0);
544 fet_beginchar ("3/4 Flat", "-3");
545 save left_wid, overlap, right_wid;
551 set_char_box (1.2 stafflinethickness#,
552 (left_wid + right_wid - overlap) * staff_space#,
553 .6 staff_space#, 1.9 staff_space#);
555 currentpicture := remember_pic;
557 draw_staff (-2, 2, 0.5);
562 fet_beginchar ("Double Sharp", "4");
563 save klaverblad, klaversteel;
567 klaversteel = 1/15 staff_space;
568 klaverblad = .4 staff_space - .5 stafflinethickness;
570 set_char_box (0, staff_space#, .5 staff_space#, .5 staff_space#);
572 z1 = (klaversteel, 0);
573 z2 = (w / 2 - klaverblad / 10, h - klaverblad);
575 z4 = z2 reflectedabout ((0, 0), (1, 1));
576 z5 = z1 reflectedabout ((0, 0), (1, 1));
578 labels (1, 2, 3, 4, 5);
580 pickup pencircle scaled blot_diameter;
582 x2 := hfloor (rt x2) - blot_diameter / 2;
583 x3 := hfloor (rt x3) - blot_diameter / 2;
584 y3 := vfloor (top y3) - blot_diameter / 2;
585 y4 := vfloor (top y4) - blot_diameter / 2;
594 .. {dir 225}(top z5);
596 -- reverse pat xscaled -1 shifted (-feta_eps, 0);
598 % assure symmetry -- it's more important to center the glyph on the
599 % staff line than centering it between staff lines, so we use
600 % feta_shift, not feta_space_shift.
603 fill pat shifted (0, feta_shift)
604 -- reverse pat yscaled -1 shifted (0, -feta_eps)
608 currentpicture := currentpicture shifted (hround (w / 2), 0);
610 remember_pic := currentpicture;
612 draw_staff (-2, 2, 0);
617 fet_beginchar ("Double Sharp", "4");
618 set_char_box (0, staff_space#,
619 .5 staff_space#, .5 staff_space#);
621 currentpicture := remember_pic;
623 draw_staff (-2, 2, 0.5);
631 leftindent := .2 staff_space;
633 set_char_box (0, .5 staff_space# + stafflinethickness#,
634 staff_space#, staff_space#);
638 z1 = (leftindent, h);
639 z2 = (w - stafflinethickness, .5 (h - d));
640 z3 = (leftindent, -d);
642 penpos1 (stafflinethickness, 35);
643 penpos2 (.1 staff_space + stafflinethickness, 0);
644 penpos3 (stafflinethickness, -35);
647 .. simple_serif (z3l, z3r, 90)
649 .. simple_serif (z1r, z1l, 90)
655 fet_beginchar ("Right Parenthesis", "rightparen");
659 remember_pic := currentpicture;
661 draw_staff (-2, 2, 0);
666 fet_beginchar ("Right Parenthesis", "rightparen");
670 remember_pic := currentpicture;
672 draw_staff (-2, 2, 0.5);
677 fet_beginchar ("Left Parenthesis", "leftparen");
680 currentpicture := currentpicture xscaled -1;
682 set_char_box (charwd, charbp, chardp, charht);
686 fet_endgroup ("accidentals");