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)
20 %\tracingequations:= tracingonline := 1;
22 fet_begingroup ("accidentals");
25 % The beams of most sharps have horizontal endings (as if drawn with
26 % a square pen). [Wanske] does not mention this, so we'll just ignore
30 def draw_meta_sharp (expr width) =
31 save interbeam, interstem;
32 save beamheight, beamwidth, beamslope;
33 save spanheight, spanwidth;
39 interbeam := 1.05 staff_space;
40 beamheight := 0.3 staff_space + stafflinethickness;
42 stemwidth := stafflinethickness + .05 staff_space;
43 roundness := 2 blot_diameter;
47 roundness + 2 spanwidth = beamwidth;
48 roundness + 2 spanheight = beamheight;
50 z2 - z1 = (beamwidth - roundness, beamheight);
52 beamslope = (y2 - y1) / (x2 - x1);
55 hspan = (spanwidth, beamslope * spanwidth);
56 vspan = (0, spanheight);
58 pickup pencircle scaled roundness;
60 beam := (rt (hspan + vspan)
61 .. top (hspan + vspan)
62 --- top (-hspan + vspan)
63 .. lft (-hspan + vspan)
64 --- lft (-hspan - vspan)
65 .. bot (-hspan - vspan)
66 --- bot (hspan - vspan)
68 --- cycle) shifted center;
69 fill (beam shifted (0, -interbeam / 2));
71 pickup pencircle scaled stemwidth;
72 x3 = x4 = xpart center;
76 fet_beginchar ("Sharp" , "2");
77 set_char_box (0, 1.1 staff_space#,
78 1.5 staff_space#, 1.5 staff_space#);
84 (bot y3) + -stemx * beamslope = -1.5 staff_space + ypart center;
85 (top y4) + stemx * beamslope = 1.5 staff_space + ypart center;
89 draw_gridline (z3 - (stemx, stemx * beamslope),
90 z4 - (stemx, stemx * beamslope),
92 addto currentpicture also currentpicture rotated 180 shifted (w, 0);
96 fet_beginchar ("1/2 Sharp" , "1");
97 set_char_box (0, 0.7 staff_space#,
98 1.5 staff_space#, 1.5 staff_space#);
103 (bot y3) + -stemx * beamslope = -1.5 staff_space + ypart center;
104 (top y4) + stemx * beamslope = 1.5 staff_space + ypart center;
108 draw_gridline (z3, z4, stemwidth);
109 addto currentpicture also currentpicture rotated 180 shifted (w, 0);
113 fet_beginchar ("3/4 Sharp", "3");
114 set_char_box (0, 1.6 staff_space#,
115 1.5 staff_space#, 1.5 staff_space#);
120 (bot y3) + -stemx * beamslope = -1.5 staff_space + ypart center;
121 (top y4) + stemx * beamslope = 1.5 staff_space + ypart center;
125 draw_gridline (z3 - (stemx, stemx * beamslope),
126 z4 - (stemx, stemx * beamslope),
128 draw_gridline (z3, z4, stemwidth);
129 addto currentpicture also currentpicture rotated 180 shifted (w,0);
134 % The stems of the natural are brushed (at least, in Barenreiter SCS)
137 fet_beginchar ("Natural", "0")
138 save height, xcenter;
139 save interbeam, interstem;
140 save beamheight, beamwidth;
141 save stemwidth, top_stem_thick;
143 beamheight# = 0.35 staff_space# + .5 stafflinethickness#;
144 height# = 1.5 staff_space#;
146 set_char_box (0, 2/3 staff_space#, height#, height#);
148 define_pixels (height);
149 define_blacker_pixels (beamheight);
151 top_stem_thick = round (stafflinethickness + .09 staff_space) + 0.4;
152 stemwidth = 0.08 staff_space + .5 stafflinethickness;
154 interstem + stemwidth = w;
156 z2 - z1 = (interstem, slope * interstem);
157 xpart .5 [z2, z1] = xcenter;
160 pickup penrazor scaled beamheight rotated 90;
161 top y2 = staff_space - 3/2 stafflinethickness;
162 slope = stafflinethickness / interstem;
171 pickup pencircle scaled stemwidth;
172 x3 := round (xpart z1);
173 x4 := round (xpart z2);
175 penpos3 (top_stem_thick, 0);
176 penpos5 (top_stem_thick, 0);
177 penpos4 (stemwidth, 0);
178 penpos6 (stemwidth, 0);
188 fill simple_serif (z3l, z3r, -30)
193 fill simple_serif (z5l, z5r, 30)
199 penlabels (3, 4, 5, 6);
205 % Dedicated to my mom. (3/10/97)
207 % Mamma, ik hou van je; kom je alsjeblieft terug?
211 % TODO: remove crook_fatness
212 % TODO: document, simplify!
214 def draw_meta_flat (expr xcenter, w, crook_fatness) =
217 save bottom_overshoot;
218 save top_stem_thick, bottom_stem_thick, hair, smaller_hole;
219 save top_crook_thinness;
225 center = (xcenter, 0);
227 % the shouldn't reach to the top staff line.
228 %% TODO: should take from height.
229 clearing = 1.2 stafflinethickness;
232 % TODO: parameterize this
234 if w >= 0.75 staff_space:
235 smaller_hole = 0.35 stafflinethickness;
237 smaller_hole = 0.0 stafflinethickness;
239 crook_thinness = .7 stafflinethickness + .06 staff_space;
240 top_crook_thinness = 1 stafflinethickness + .065 staff_space;
242 % this is a somewhat heuristic. We should probably make it
243 % straight for low resolution (300 dpi and less).
245 round (0.1 staff_space + 1.2 stafflinethickness) + 0.74;
247 bottom_overshoot = stafflinethickness;
248 bottom_stem_thick = 0.06 staff_space + 0.6 stafflinethickness;
250 z1 = (0, 2 staff_space)
252 - (0, stafflinethickness / 2 + clearing);
253 z2 = (0, -1/2 staff_space - stafflinethickness / 2)
256 penpos1 (top_stem_thick, 0);
257 penpos2 (bottom_stem_thick, 0);
259 y3l = (staff_space - stafflinethickness) / 2 + ypart center;
260 z3l = whatever [z2r, z1r];
261 z3r = .3 [z2r, z1r] + (smaller_hole, 0);
263 % we insert z3l to get better conversion with mf2pt1
264 fill simple_serif (z1r, z1l, 30)
270 z10 = whatever [z2r, z1r] + (smaller_hole, 0);
272 + (bottom_overshoot / 3,
273 -staff_space / 2 - stafflinethickness / 2)
274 - (0, bottom_overshoot);
276 penpos4 (whatever, 53);
278 y4l - y4r = top_crook_thinness;
279 y5r = .15 staff_space + ypart center;
280 x5l = w + xpart center;
281 y4 = ypart center + staff_space / 2;
282 x4r = .45 [x5r, x3r];
284 penpos5 (crook_fatness, -175);
288 bot_crook_dir = unitvector ((x5l, 0) - z11);
289 z8 = z11 + whatever * bot_crook_dir;
290 y8 = -staff_space / 2 + 0.0 * stafflinethickness;
293 + whatever * bot_crook_dir
294 + crook_thinness * (bot_crook_dir rotated 90);
297 penlabels (range 0 thru 11);
299 y10 = -1/10 staff_space;
300 % draw_staff (-2, 2, 0.5);
301 % draw_staff (-2, 2, 0.0);
303 unfill z3r{z3r - z10}
306 .. z7{-bot_crook_dir}
322 % unfortunately, 600dpi is not enough to show the brush of the stem.
325 fet_beginchar ("Flat", "-2")
326 set_char_box (1.2 stafflinethickness#, .8 staff_space#,
327 0.6 staff_space#, 1.9 staff_space#);
328 draw_meta_flat (0, w, 0.31 staff_space);
332 fet_beginchar ("Semi flat", "-1")
333 set_char_box (1.2 stafflinethickness#, .8 staff_space#,
334 0.6 staff_space#, 1.9 staff_space#);
335 draw_meta_flat(0, w, 0.31 staff_space);
336 currentpicture := currentpicture xscaled -1 shifted (w - b, 0);
340 fet_beginchar ("Double Flat", "-4")
341 save left_wid, overlap, right_wid;
346 set_char_box (1.2 stafflinethickness#,
347 (left_wid + right_wid -overlap) * staff_space#,
348 .6 staff_space#, 1.9 staff_space#);
349 draw_meta_flat (0, left_wid * staff_space, 1/3 staff_space);
350 draw_meta_flat (round ((left_wid - overlap) * staff_space),
351 right_wid * staff_space, 0.33 staff_space);
355 fet_beginchar ("3/4 Flat", "-3")
356 save left_wid, overlap, right_wid;
361 set_char_box (1.2 stafflinethickness#,
362 (left_wid + right_wid - overlap) * staff_space#,
363 .6 staff_space#, 1.9 staff_space#);
364 draw_meta_flat (0, left_wid * staff_space, 1/3 staff_space);
365 draw_meta_flat (round ((left_wid - overlap) * staff_space),
366 right_wid * staff_space, 0.33 staff_space);
368 %% maybe we should clip part of the stems?
369 %% or make the 1st flat smaller?
371 pickup pencircle scaled 2 stafflinethickness;
372 z12 = (-.25 w - b, .55 staff_space);
373 z13 = (.75 w, 1.45 staff_space);
374 penpos12 (2 stafflinethickness, angle (z13 - z12) - 90);
375 penpos13 (2 stafflinethickness, angle (z13 - z12) - 90);
376 z14 = z12 - stafflinethickness * unitvector (z13 - z12);
377 z15 = z13 + stafflinethickness * unitvector (z13 - z12);
393 fet_beginchar ("Double Sharp", "4")
394 set_char_box (0, staff_space#, .5 staff_space#, .5 staff_space#);
395 save klaverblad, klaversteel;
397 klaversteel = 1/15 staff_space;
398 klaverblad = .40 staff_space - .5 stafflinethickness;
400 z1 = (klaversteel, 0);
401 z2 = (w / 2 - klaverblad / 10, h - klaverblad);
403 z4 = z2 reflectedabout ((0, 0), (1, 1));
404 z5 = z1 reflectedabout ((0, 0), (1, 1));
406 labels (1, 2, 3, 4, 5);
411 pickup pencircle scaled blot_diameter;
419 .. {dir 225}(top z5);
421 & reverse pat xscaled (-1);
423 & reverse pat yscaled (-d / h)
428 currentpicture := currentpicture shifted (w / 2, 0);
434 leftindent# := .2 staff_space#;
435 define_pixels (leftindent);
437 set_char_box (0, .5 staff_space# + stafflinethickness#,
438 staff_space#, staff_space#);
440 z1 = (leftindent, h);
441 z2 = (w - stafflinethickness, 0);
442 z3 = (leftindent, -d);
444 penpos1 (stafflinethickness, 35);
445 penpos2 (.1 staff_space + stafflinethickness, 0);
446 penpos3 (stafflinethickness, -35);
451 .. simple_serif (z3l, z3r, 90)
453 .. simple_serif (z1r, z1l, 90)
459 fet_beginchar ("Right Parenthesis", "rightparen")
464 fet_beginchar ("Left Parenthesis", "leftparen")
466 currentpicture := currentpicture xscaled -1;
467 set_char_box (charwd, charbp, chardp, charht);
471 fet_endgroup ("accidentals");