2 % feta-bolletjes.mf -- implement noteheads
4 % source file of LilyPond's pretty-but-neat music font
6 % (c) 1997--2003 Jan Nieuwenhuizen <janneke@gnu.org>
7 % & Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 % & Juergen Reuter <reuter@ipd.uka.de>
14 % most beautiful noteheads are pronounced, not circular,
15 % and not even symmetric.
16 % These examples are inspired by [Wanske], see literature list
20 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
22 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
23 save black_notehead_width, noteheight,
24 slash_thick, slash_slope, overdone_heads;
25 numeric black_notehead_width, noteheight, slash_thick;
27 fet_begingroup("noteheads");
31 % slope of slash. From scm/grob-description.scm. How to auto-copy?
34 % thickness of slash lines. quarter notes get 1.5slt width.
35 slash_thick# := 2/3*0.48staff_space#;
39 % Hand-engraved music often has balls extending above and below
40 % the lines. If you like that, modify overdone heads (unit:
44 noteheight#:=staff_space#+ (1 + overdone_heads) *stafflinethickness#;
46 define_pixels(slash_thick, noteheight);
49 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
51 % SLANT moves both extremes on the long axis (by SLANT * ELLIPSIDITY,
52 % so SLANT = -1, puts the extreme on the long axis next to the short axis one.)
55 def draw_outside_ellipse (expr ellipsidity, tilt, superness,
61 p := superellipse ((ellipsidity, 0), (-slant * ellipsidity, 1.0),
62 (- ellipsidity, 0), (slant * ellipsidity, -1.0), superness);
66 save top_point, right_point;
67 pair top_point, right_point;
69 top_point := directionpoint left of p;
70 right_point := directionpoint up of p;
72 save scaling, width, height;
74 scaling# = noteheight# /(2 ypart (top_point));
75 width# := 2 xpart (right_point) * scaling#;
77 define_pixels (width, scaling);
79 set_char_box (0, width#, noteheight#/2, noteheight#/2);
82 charwy := ypart (right_point) * scaling#;
85 p := p scaled scaling shifted (width/2, 0) ;
87 pickup pencircle scaled 1 ; draw p;
94 def undraw_inside_ellipse (expr ellipsidity, tilt, superness, clearance,
100 p := superellipse ((ellipsidity, 0), (0, 1.0),
101 (- ellipsidity, 0), (0, -1.0), superness);
105 save top_point, right_point;
106 pair top_point, right_point;
108 top_point := directionpoint left of p;
109 right_point := directionpoint up of p;
111 save height, scaling;
113 height# = staff_space# + stafflinethickness# - clearance;
114 scaling# = height# /(2 ypart (top_point));
116 define_pixels (scaling);
117 p := (p scaled scaling) shifted center;
119 if test_outlines = 1:
120 pickup pencircle scaled 1; draw p;
132 % dimensions aren't entirely right.
134 fet_beginchar ("Brevis notehead", "-1", "brevishead");
135 save stemthick, fudge;
136 define_pixels (stemthick);
137 fudge = blot_diameter /2;
138 stemthick# = 2 stafflinethickness#;
140 draw_outside_ellipse (1.80, 0, 0.707, 0);
141 undraw_inside_ellipse (1.30, 125, 0.68, 2 stafflinethickness#,
144 pickup pencircle scaled stemthick;
156 draw_gridline(z1,z2,stemthick);
157 draw_gridline(z3,z4,stemthick);
163 fet_beginchar("Whole notehead", "0", "wholehead")
164 draw_outside_ellipse (1.80 - puff_up_factor / 3.0, 0, 0.707, 0);
165 undraw_inside_ellipse (1.30, 125 - puff_up_factor *10,
166 0.68, 2 stafflinethickness#,
169 % draw_staff_outline (-2, 2, 0.5);
174 fet_beginchar("Half notehead", "1", "halfhead")
175 draw_outside_ellipse (1.53 - puff_up_factor / 3.0, 34, 0.66, 0.17);
176 undraw_inside_ellipse (3.25, 33, 0.81,
177 2.5 stafflinethickness#, (w/2, 0));
181 fet_beginchar("Quart notehead", "2", "quarthead")
182 draw_outside_ellipse (1.54 - puff_up_factor / 2.0, 32, 0.707, 0);
183 black_notehead_width# := charwd;
188 fet_beginchar("Quart noteheadPQ", "2PQ", "quartheadPQ")
189 draw_outside_ellipse (1.0 - puff_up_factor / 2.0, 32, 0.707, 0);
192 fet_beginchar("Quart noteheadAA", "2AA", "quartheadAA")
193 draw_outside_ellipse (1.35 - puff_up_factor / 2.0, 32, 0.707, 0);
196 fet_beginchar("Quart noteheadAB", "2AB", "quartheadAB")
197 draw_outside_ellipse (1.4 - puff_up_factor / 2.0, 32, 0.707, 0);
200 fet_beginchar("Quart noteheadAC", "2AC", "quartheadAC")
201 draw_outside_ellipse (1.45 - puff_up_factor / 2.0, 32, 0.707, 0);
204 fet_beginchar("Quart noteheadAD", "2AD", "quartheadAD")
205 draw_outside_ellipse (1.5 - puff_up_factor / 2.0, 32, 0.707, 0);
208 fet_beginchar("Quart noteheadAD", "2AE", "quartheadAD")
209 draw_outside_ellipse (1.55 - puff_up_factor / 2.0, 32, 0.707, 0);
212 fet_beginchar("Quart noteheadAD", "2AF", "quartheadAD")
213 draw_outside_ellipse (1.6 - puff_up_factor / 2.0, 32, 0.707, 0);
215 fet_beginchar("Quart noteheadAD", "2AG", "quartheadAD")
216 draw_outside_ellipse (1.65 - puff_up_factor / 2.0, 32, 0.707, 0);
220 fet_beginchar("Quart noteheadBA", "2BA", "quartheadBA")
221 draw_outside_ellipse (1.35 - puff_up_factor / 2.0, 35, 0.707, 0);
223 fet_beginchar("Quart noteheadBB", "2BB", "quartheadBB")
224 draw_outside_ellipse (1.4 - puff_up_factor / 2.0, 35, 0.707, 0);
227 fet_beginchar("Quart noteheadBC", "2BC", "quartheadBC")
228 draw_outside_ellipse (1.45 - puff_up_factor / 2.0, 35, 0.707, 0);
230 fet_beginchar("Quart noteheadBD", "2BD", "quartheadBD")
231 draw_outside_ellipse (1.5 - puff_up_factor / 2.0, 35, 0.707, 0);
233 fet_beginchar("Quart noteheadBD", "2BE", "quartheadBD")
234 draw_outside_ellipse (1.55 - puff_up_factor / 2.0, 35, 0.707, 0);
236 fet_beginchar("Quart noteheadBD", "2BF", "quartheadBD")
237 draw_outside_ellipse (1.6 - puff_up_factor / 2.0, 35, 0.707, 0);
239 fet_beginchar("Quart noteheadBD", "2BG", "quartheadBD")
240 draw_outside_ellipse (1.65 - puff_up_factor / 2.0, 35, 0.707, 0);
245 fet_beginchar("Quart noteheadCA", "2CA", "quartheadCA")
246 draw_outside_ellipse (1.35 - puff_up_factor / 2.0, 40, 0.707, 0);
248 fet_beginchar("Quart noteheadCB", "2CB", "quartheadCB")
249 draw_outside_ellipse (1.4 - puff_up_factor / 2.0, 40, 0.707, 0);
251 fet_beginchar("Quart noteheadCC", "2CC", "quartheadCC")
252 draw_outside_ellipse (1.45 - puff_up_factor / 2.0, 40, 0.707, 0);
254 fet_beginchar("Quart noteheadCD", "2CD", "quartheadCD")
255 draw_outside_ellipse (1.5 - puff_up_factor / 2.0, 40, 0.707, 0);
257 fet_beginchar("Quart noteheadCD", "2CE", "quartheadCD")
258 draw_outside_ellipse (1.55 - puff_up_factor / 2.0, 40, 0.707, 0);
260 fet_beginchar("Quart noteheadCD", "2CF", "quartheadCD")
261 draw_outside_ellipse (1.6 - puff_up_factor / 2.0, 40, 0.707, 0);
263 fet_beginchar("Quart noteheadCD", "2CG", "quartheadCD")
264 draw_outside_ellipse (1.65 - puff_up_factor / 2.0, 40, 0.707, 0);
267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270 fet_beginchar("Whole diamondhead", "0diamond", "wholediamondhead")
271 draw_outside_ellipse (1.80, 0, 0.495, 0);
272 undraw_inside_ellipse (1.30, 125, 0.6,
273 .4 staff_space# + stafflinethickness#,
278 fet_beginchar("Half diamondhead", "1diamond",
281 draw_outside_ellipse (1.50, 34, 0.49, 0.17);
282 undraw_inside_ellipse (3.5, 33, 0.80,
283 .3 staff_space# + 1.5 stafflinethickness#, (w/2, 0));
287 fet_beginchar("Quart diamondheadh", "2diamondh", "diamondheadh")
288 draw_outside_ellipse (1.80, 35, 0.495, -0.25);
291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
298 save triangle,kern; path triangle;
299 save left_point, height, width;
300 pair exact_left_point;
302 pen_thick# = stafflinethickness# + .1 staff_space#;
303 define_pixels(pen_thick);
305 exact_left_point := llap# * dir (90 + tilt);
306 height# = max (ypart exact_left_point,
307 -ypart (exact_left_point rotated 120)) + pen_thick#/2;
309 kern# = 1/3 xpart (exact_left_point - (exact_left_point rotated 120));
310 width# = xpart (-exact_left_point + (exact_left_point rotated 240));
311 define_pixels (kern);
312 z1 = (hround_pixels (xpart exact_left_point), vround_pixels (ypart exact_left_point));
316 z12 = caveness[.5[z1,z2],z3];
317 z23 = z12 rotated 120;
318 z31 = z12 rotated 240;
319 triangle = z1 .. z12 .. z2 ..
323 triangle := triangle shifted (-x1+pen_thick/2-kern,0) xscaled xs;
324 pickup pencircle scaled pen_thick xscaled xs;
325 % labels(1,2,12,23,31,3);
326 set_char_box(0, width# - kern#+ pen_thick#, height#, height#);
329 fet_beginchar("Whole trianglehead", "0triangle", "wholetrianglehead")
335 llap# = 3/4noteheight#;
343 fet_beginchar("Half trianglehead", "1triangle", "halftrianglehead")
349 llap# = 2/3noteheight#;
356 fet_beginchar("Quart trianglehead", "2triangle", "trianglehead")
361 llap# = 2/3noteheight#;
368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
370 % slash heads are for indicating improvisation. They are
371 % twice as high as normal heads.
373 def draw_slash(expr hwid_hash) =
377 exact_height = staff_space# + stafflinethickness#/2;
379 set_char_box (0, 2 exact_height / slash_slope + hwid_hash,
380 exact_height, exact_height);
386 pickup pencircle scaled blot_diameter;
391 lft x2 = 2 h / slash_slope;
398 ne_dir := unitvector( z3 - z4);
399 filldraw z1 --- z2 --- z3 --- z4 --- cycle;
401 if hwid_hash > 2 slash_thick#:
404 th = slash_thick - blot_diameter;
409 z6 - z5 = whatever * ne_dir;
410 z8 - z7 = whatever * ne_dir;
412 z5 = z1 + whatever * ne_dir + th * (ne_dir rotated -90);
413 z8 = z4 + whatever * ne_dir + th * (ne_dir rotated 90);
416 z5 -- z6 -- z7 -- z8 -- cycle;
418 labels (range 1 thru 10);
421 fet_beginchar("Whole slashhead","0slash","wholeslashhead")
422 draw_slash(4 slash_thick# + 0.5 staff_space#);
425 fet_beginchar("Half slashhead","1slash","halfslashhead")
426 draw_slash(3.0 slash_thick# + 0.15 staff_space#);
429 fet_beginchar("Quart slashhead","2slash","quartslashhead")
430 draw_slash(1.5 slash_thick#);
433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
434 % thick is the distance between the NE/SW parallel lines in the cross
435 % (distance between centres of lines)
436 % in stafflinethickness def
438 def draw_cross(expr thick) =
439 save pent, slant, ne_dir;
443 pen_thick# := 1.2stafflinethickness#;
444 define_pixels (pen_thick);
445 pickup pencircle scaled pen_thick;
448 ne_dir := unitvector ((1, (2 h -pen_thick)/(w - pen_thick)));
451 z4 - z5 = whatever * ne_dir;
453 z6 - z3 = whatever * ne_dir;
454 z3 - z4 = whatever * (ne_dir yscaled -1);
456 z4 - z3 = whatever * (ne_dir) + (ne_dir rotated -90) * thick * stafflinethickness;
458 x1 = charwd/2 - .5 pen_thick#;
459 z1 = whatever * ne_dir + thick/2 * stafflinethickness# * (ne_dir rotated -90);
462 labels (1,2,3,4,5,6);
464 crz = (z6 -- z3 -- z4 -- z5) ;
466 draw crz shifted(w/2,0);
467 draw crz xscaled -1 shifted(w/2,0);
468 draw crz yscaled -1 shifted(w/2,0);
469 draw crz scaled -1 shifted(w/2,0);
473 message (decimal charwx);
474 message (decimal charwy);
475 z12 = (charwx * hppp, y1 * vppp);
479 fet_beginchar("Whole Crossed notehead", "0cross", "wholecrossedhead")
480 wid# := black_notehead_width#+4stafflinethickness#;
481 hei# := noteheight#+stafflinethickness#;
482 set_char_box(0, wid#,hei#/2,hei#/2);
487 fet_beginchar("Half Crossed notehead", "1cross", "halfcrossedhead")
488 wid# := black_notehead_width#+2stafflinethickness#;
489 hei# := noteheight#+stafflinethickness#/2;
490 set_char_box(0, wid#,hei#/2,hei#/2);
494 fet_beginchar("Crossed notehead", "2cross", "crossedhead")
495 wid# := black_notehead_width#;
497 set_char_box(0, wid#,hei#/2,hei#/2);
501 fet_beginchar("X-Circled notehead", "2xcircle", "xcircledhead")
502 wid# := black_notehead_width#*sqrt(sqrt2);
503 hei# := noteheight#*sqrt(sqrt2);
504 set_char_box(0, wid#,hei#/2,hei#/2);
505 cthick := (1.2+1/4)*stafflinethickness;
508 pickup pencircle scaled cthick;
509 draw fullcircle xscaled 2cxr yscaled 2cyr shifted (w/2,0);
512 draw (-xpos+w/2,-ypos) -- (xpos+w/2,ypos);
513 draw (-xpos+w/2,ypos) -- (xpos+w/2,-ypos);
518 z12 = (charwx * hppp , charwy * vppp );
524 fet_endgroup("noteheads");
526 define_pixels(black_notehead_width);