2 % feta-bolletjes.mf -- implement noteheads
4 % source file of LilyPond's pretty-but-neat music font
6 % (c) 1997--2004 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;
28 fet_begingroup("noteheads");
32 % slope of slash. From scm/grob-description.scm. How to auto-copy?
35 % thickness of slash lines. quarter notes get 1.5slt width.
36 slash_thick# := 2/3*0.48staff_space#;
40 % Hand-engraved music often has balls extending above and below
41 % the lines. If you like that, modify overdone heads (unit:
45 noteheight#:=staff_space#+ (1 + overdone_heads) *stafflinethickness#;
47 define_pixels(slash_thick, noteheight);
50 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52 % SLANT moves both extremes on the long axis (by SLANT * ELLIPSIDITY,
53 % so SLANT = -1, puts the extreme on the long axis next to the short axis one.)
56 def draw_outside_ellipse (expr ellipsidity, tilt, superness,
62 p := superellipse ((ellipsidity, 0), (-slant * ellipsidity, 1.0),
63 (- ellipsidity, 0), (slant * ellipsidity, -1.0), superness);
67 save top_point, right_point;
68 pair top_point, right_point;
70 top_point := directionpoint left of p;
71 right_point := directionpoint up of p;
73 save scaling, width, height;
75 scaling# = noteheight# /(2 ypart (top_point));
76 width# := 2 xpart (right_point) * scaling#;
78 define_pixels (width, scaling);
80 set_char_box (0, width#, noteheight#/2, noteheight#/2);
83 charwy := ypart (right_point) * scaling#;
86 p := p scaled scaling shifted (width/2, 0) ;
88 pickup pencircle scaled 1 ; draw p;
95 def undraw_inside_ellipse (expr ellipsidity, tilt, superness, clearance,
101 p := superellipse ((ellipsidity, 0), (0, 1.0),
102 (- ellipsidity, 0), (0, -1.0), superness);
106 save top_point, right_point;
107 pair top_point, right_point;
109 top_point := directionpoint left of p;
110 right_point := directionpoint up of p;
112 save height, scaling;
114 height# = staff_space# + stafflinethickness# - clearance;
115 scaling# = height# /(2 ypart (top_point));
117 define_pixels (scaling);
118 p := (p scaled scaling) shifted center;
120 if test_outlines = 1:
121 pickup pencircle scaled 1; draw p;
133 % dimensions aren't entirely right.
135 fet_beginchar ("Brevis notehead", "-1", "brevishead");
136 save stemthick, fudge;
137 define_pixels (stemthick);
138 fudge = blot_diameter /2;
139 stemthick# = 2 stafflinethickness#;
141 draw_outside_ellipse (1.80, 0, 0.707, 0);
142 undraw_inside_ellipse (1.30, 125, 0.68, 2 stafflinethickness#,
145 pickup pencircle scaled stemthick;
157 draw_gridline(z1,z2,stemthick);
158 draw_gridline(z3,z4,stemthick);
164 fet_beginchar("Whole notehead", "0", "wholehead")
165 draw_outside_ellipse (1.80 - puff_up_factor / 3.0, 0, 0.707, 0);
166 undraw_inside_ellipse (1.30, 125 - puff_up_factor *10,
167 0.68, 2 stafflinethickness#,
170 % draw_staff_outline (-2, 2, 0.5);
175 fet_beginchar("Half notehead", "1", "halfhead")
176 draw_outside_ellipse (1.53 - puff_up_factor / 3.0, 34, 0.66, 0.17);
177 undraw_inside_ellipse (3.25, 33, 0.81,
178 2.5 stafflinethickness#, (w/2, 0));
182 fet_beginchar("Quart notehead", "2", "quarthead")
184 % used to have 32. With 31, they are slightly bolder.
185 draw_outside_ellipse (1.49 - puff_up_factor / 3.0, 31, 0.707, 0);
186 black_notehead_width# := charwd;
195 fet_beginchar("Quart noteheadPQ", "2PQ", "quartheadPQ")
196 draw_outside_ellipse (1.0 - puff_up_factor / 2.0, 32, 0.707, 0);
199 fet_beginchar("Quart noteheadAA", "2AA", "quartheadAA")
200 draw_outside_ellipse (1.35 - puff_up_factor / 2.0, 32, 0.707, 0);
203 fet_beginchar("Quart noteheadAB", "2AB", "quartheadAB")
204 draw_outside_ellipse (1.4 - puff_up_factor / 2.0, 32, 0.707, 0);
207 fet_beginchar("Quart noteheadAC", "2AC", "quartheadAC")
208 draw_outside_ellipse (1.45 - puff_up_factor / 2.0, 32, 0.707, 0);
211 fet_beginchar("Quart noteheadAD", "2AD", "quartheadAD")
212 draw_outside_ellipse (1.5 - puff_up_factor / 2.0, 32, 0.707, 0);
215 fet_beginchar("Quart noteheadAD", "2AE", "quartheadAD")
216 draw_outside_ellipse (1.55 - puff_up_factor / 2.0, 32, 0.707, 0);
219 fet_beginchar("Quart noteheadAD", "2AF", "quartheadAD")
220 draw_outside_ellipse (1.6 - puff_up_factor / 2.0, 32, 0.707, 0);
222 fet_beginchar("Quart noteheadAD", "2AG", "quartheadAD")
223 draw_outside_ellipse (1.65 - puff_up_factor / 2.0, 32, 0.707, 0);
227 fet_beginchar("Quart noteheadBA", "2BA", "quartheadBA")
228 draw_outside_ellipse (1.35 - puff_up_factor / 2.0, 35, 0.707, 0);
230 fet_beginchar("Quart noteheadBB", "2BB", "quartheadBB")
231 draw_outside_ellipse (1.4 - puff_up_factor / 2.0, 35, 0.707, 0);
234 fet_beginchar("Quart noteheadBC", "2BC", "quartheadBC")
235 draw_outside_ellipse (1.45 - puff_up_factor / 2.0, 35, 0.707, 0);
237 fet_beginchar("Quart noteheadBD", "2BD", "quartheadBD")
238 draw_outside_ellipse (1.5 - puff_up_factor / 2.0, 35, 0.707, 0);
240 fet_beginchar("Quart noteheadBD", "2BE", "quartheadBD")
241 draw_outside_ellipse (1.55 - puff_up_factor / 2.0, 35, 0.707, 0);
243 fet_beginchar("Quart noteheadBD", "2BF", "quartheadBD")
244 draw_outside_ellipse (1.6 - puff_up_factor / 2.0, 35, 0.707, 0);
246 fet_beginchar("Quart noteheadBD", "2BG", "quartheadBD")
247 draw_outside_ellipse (1.65 - puff_up_factor / 2.0, 35, 0.707, 0);
252 fet_beginchar("Quart noteheadCA", "2CA", "quartheadCA")
253 draw_outside_ellipse (1.35 - puff_up_factor / 2.0, 40, 0.707, 0);
255 fet_beginchar("Quart noteheadCB", "2CB", "quartheadCB")
256 draw_outside_ellipse (1.4 - puff_up_factor / 2.0, 40, 0.707, 0);
258 fet_beginchar("Quart noteheadCC", "2CC", "quartheadCC")
259 draw_outside_ellipse (1.45 - puff_up_factor / 2.0, 40, 0.707, 0);
261 fet_beginchar("Quart noteheadCD", "2CD", "quartheadCD")
262 draw_outside_ellipse (1.5 - puff_up_factor / 2.0, 40, 0.707, 0);
264 fet_beginchar("Quart noteheadCD", "2CE", "quartheadCD")
265 draw_outside_ellipse (1.55 - puff_up_factor / 2.0, 40, 0.707, 0);
267 fet_beginchar("Quart noteheadCD", "2CF", "quartheadCD")
268 draw_outside_ellipse (1.6 - puff_up_factor / 2.0, 40, 0.707, 0);
270 fet_beginchar("Quart noteheadCD", "2CG", "quartheadCD")
271 draw_outside_ellipse (1.65 - puff_up_factor / 2.0, 40, 0.707, 0);
276 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
279 fet_beginchar("Whole diamondhead", "0diamond", "wholediamondhead")
280 draw_outside_ellipse (1.80, 0, 0.495, 0);
281 undraw_inside_ellipse (1.30, 125, 0.6,
282 .4 staff_space# + stafflinethickness#,
287 fet_beginchar("Half diamondhead", "1diamond",
290 draw_outside_ellipse (1.50, 34, 0.49, 0.17);
291 undraw_inside_ellipse (3.5, 33, 0.80,
292 .3 staff_space# + 1.5 stafflinethickness#, (w/2, 0));
296 fet_beginchar("Quart diamondhead", "2diamond", "diamondhead")
297 draw_outside_ellipse (1.80, 35, 0.495, -0.25);
300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307 save triangle,kern; path triangle;
308 save left_point, height, width;
309 pair exact_left_point;
311 pen_thick# = stafflinethickness# + .1 staff_space#;
312 define_pixels(pen_thick);
314 exact_left_point := llap# * dir (90 + tilt);
315 height# = max (ypart exact_left_point,
316 -ypart (exact_left_point rotated 120)) + pen_thick#/2;
318 kern# = 1/3 xpart (exact_left_point - (exact_left_point rotated 120));
319 width# = xpart (-exact_left_point + (exact_left_point rotated 240));
320 define_pixels (kern);
321 z1 = (hround_pixels (xpart exact_left_point), vround_pixels (ypart exact_left_point));
325 z12 = caveness[.5[z1,z2],z3];
326 z23 = z12 rotated 120;
327 z31 = z12 rotated 240;
328 triangle = z1 .. z12 .. z2 ..
332 triangle := triangle shifted (-x1+pen_thick/2-kern,0) xscaled xs;
333 pickup pencircle scaled pen_thick xscaled xs;
334 % labels(1,2,12,23,31,3);
335 set_char_box(0, width# - kern#+ pen_thick#, height#, height#);
338 fet_beginchar("Whole trianglehead", "0triangle", "wholetrianglehead")
344 llap# = 3/4noteheight#;
352 fet_beginchar("Half trianglehead", "1triangle", "halftrianglehead")
358 llap# = 2/3noteheight#;
365 fet_beginchar("Quart trianglehead", "2triangle", "trianglehead")
370 llap# = 2/3noteheight#;
377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
379 % slash heads are for indicating improvisation. They are
380 % twice as high as normal heads.
382 def draw_slash(expr hwid_hash) =
386 exact_height = staff_space# + stafflinethickness#/2;
388 set_char_box (0, 2 exact_height / slash_slope + hwid_hash,
389 exact_height, exact_height);
395 pickup pencircle scaled blot_diameter;
400 lft x2 = 2 h / slash_slope;
407 ne_dir := unitvector( z3 - z4);
408 filldraw z1 --- z2 --- z3 --- z4 --- cycle;
410 if hwid_hash > 2 slash_thick#:
413 th = slash_thick - blot_diameter;
418 z6 - z5 = whatever * ne_dir;
419 z8 - z7 = whatever * ne_dir;
421 z5 = z1 + whatever * ne_dir + th * (ne_dir rotated -90);
422 z8 = z4 + whatever * ne_dir + th * (ne_dir rotated 90);
425 z5 -- z6 -- z7 -- z8 -- cycle;
427 labels (range 1 thru 10);
430 fet_beginchar("Whole slashhead","0slash","wholeslashhead")
431 draw_slash(4 slash_thick# + 0.5 staff_space#);
434 fet_beginchar("Half slashhead","1slash","halfslashhead")
435 draw_slash(3.0 slash_thick# + 0.15 staff_space#);
438 fet_beginchar("Quart slashhead","2slash","quartslashhead")
439 draw_slash(1.5 slash_thick#);
442 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
443 % thick is the distance between the NE/SW parallel lines in the cross
444 % (distance between centres of lines)
445 % in stafflinethickness def
447 def draw_cross(expr thick) =
448 save pent, slant, ne_dir;
452 pen_thick# := 1.2stafflinethickness#;
453 define_pixels (pen_thick);
454 pickup pencircle scaled pen_thick;
457 ne_dir := unitvector ((1, (2 h -pen_thick)/(w - pen_thick)));
460 z4 - z5 = whatever * ne_dir;
462 z6 - z3 = whatever * ne_dir;
463 z3 - z4 = whatever * (ne_dir yscaled -1);
465 z4 - z3 = whatever * (ne_dir) + (ne_dir rotated -90) * thick * stafflinethickness;
467 x1 = charwd/2 - .5 pen_thick#;
468 z1 = whatever * ne_dir + thick/2 * stafflinethickness# * (ne_dir rotated -90);
471 labels (1,2,3,4,5,6);
473 crz = (z6 -- z3 -- z4 -- z5) ;
475 draw crz shifted(w/2,0);
476 draw crz xscaled -1 shifted(w/2,0);
477 draw crz yscaled -1 shifted(w/2,0);
478 draw crz scaled -1 shifted(w/2,0);
482 message (decimal charwx);
483 message (decimal charwy);
484 z12 = (charwx * hppp, y1 * vppp);
488 fet_beginchar("Whole Crossed notehead", "0cross", "wholecrossedhead")
489 wid# := black_notehead_width#+4stafflinethickness#;
490 hei# := noteheight#+stafflinethickness#;
491 set_char_box(0, wid#,hei#/2,hei#/2);
496 fet_beginchar("Half Crossed notehead", "1cross", "halfcrossedhead")
497 wid# := black_notehead_width#+2stafflinethickness#;
498 hei# := noteheight#+stafflinethickness#/2;
499 set_char_box(0, wid#,hei#/2,hei#/2);
503 fet_beginchar("Crossed notehead", "2cross", "crossedhead")
504 wid# := black_notehead_width#;
506 set_char_box(0, wid#,hei#/2,hei#/2);
510 fet_beginchar("X-Circled notehead", "2xcircle", "xcircledhead")
511 wid# := black_notehead_width#*sqrt(sqrt2);
512 hei# := noteheight#*sqrt(sqrt2);
513 set_char_box(0, wid#,hei#/2,hei#/2);
514 cthick := (1.2+1/4)*stafflinethickness;
517 pickup pencircle scaled cthick;
518 draw fullcircle xscaled 2cxr yscaled 2cyr shifted (w/2,0);
521 draw (-xpos+w/2,-ypos) -- (xpos+w/2,ypos);
522 draw (-xpos+w/2,ypos) -- (xpos+w/2,-ypos);
527 z12 = (charwx * hppp , charwy * vppp );
542 def generic_draw_solfa_note_shape =
543 save a,beta,black,white;
546 pickup pencircle scaled stafflinethickness;
547 2 beta# = noteheight#;
549 wid# := 2a#+stafflinethickness#;
550 hei# := noteheight#+stafflinethickness#;
551 set_char_box(0, wid#,0.5 hei#, 0.5 hei#);
553 define_pixels(a,beta);
555 black = noteshape xscaled a yscaled beta shifted (a+stafflinethickness/2,0);
559 white = noteishape xscaled (a*ai_a) yscaled (beta*bi_b)
560 shifted ((dx+1)*(a+stafflinethickness/2),dy*(beta+stafflinethickness/2));
565 def draw_solfa_note_shape =
566 save solid; boolean solid;
568 generic_draw_solfa_note_shape;
570 def draw_solfa_quarter_note_shape =
571 save solid; boolean solid;
573 generic_draw_solfa_note_shape;
576 % do - equilateral triangle: (0,-h/2) -- (w/2,h/2) -- (w,-h/2) -- cycle;
577 % stem attachment: -h/2
579 save triangle; path triangle;
580 triangle := (-1,-1) -- (0,1) -- (1,-1) -- cycle;
583 save noteshape, noteishape, dx, dy, ai_a, bi_b;
584 path noteshape, noteishape;
585 noteshape = noteishape = triangle;
587 (ai_a,bi_b)=(i_o,i_o);
588 draw_solfa_note_shape;
591 fet_beginchar("Whole dohead", "0do", "wholedohead")
592 pickup pencircle scaled blot_diameter;
600 fet_beginchar("Half dohead", "1do", "halfdohead")
608 fet_beginchar("Quart dohead", "2do", "dohead")
613 noteshape = triangle;
614 draw_solfa_quarter_note_shape;
618 % re - flat top, curved bottom:
619 % (0,h/2) {dir -90} .. (w/2,-h/2) .. {dir 90} (w,h/2) -- cycle;
620 % (broader along the base and with more vertical sides for half and
622 % stem attachment: h/2
624 save reshape; path reshape;
625 reshape = (-1,1)--(-1,0.2){down} ... (0,-1) ... {up}(1,0.2)--(1,1)--cycle;
627 fet_beginchar("Whole rehead", "0re", "wholerehead")
628 save a_b, ai_a, bi_b, dx, dy, noteshape, noteishape;
629 path noteshape, noteishape;
631 noteishape = reshape;
636 draw_solfa_note_shape;
639 fet_beginchar("Half rehead", "1re", "halfrehead")
640 save a_b, ai_a, bi_b, dx, dy, noteshape, noteishape;
641 path noteshape, noteishape;
643 noteishape = reshape;
648 draw_solfa_note_shape;
651 fet_beginchar("Quart rehead", "2ro", "rehead")
657 draw_solfa_quarter_note_shape;
660 % me - diamond: (0,0) -- (w/2,h/2) -- (w,0) -- (w/2,-h/2) -- cycle;
661 % similar to existing diamond shaped head, but not quite the same
664 save mishape; path mishape;
665 mishape = (-1,0)--(0,1)--(1,0)--(0,-1)--cycle;
667 fet_beginchar("Whole mihead", "0mi", "wholemihead")
668 save a_b, ai_a, bi_b, dx, dy, noteshape, noteishape;
669 path noteshape, noteishape;
671 noteishape = (mishape slanted -0.35) rotated -10.5;
676 draw_solfa_note_shape;
679 fet_beginchar("Half mihead", "1mi", "halfmihead")
680 save a_b, ai_a, bi_b, dx, dy, noteshape, noteishape;
681 path noteshape, noteishape;
683 noteishape = (mishape slanted -0.35) rotated -10.5;
688 draw_solfa_note_shape;
691 fet_beginchar("Quart mihead", "2mi", "mihead")
697 draw_solfa_quarter_note_shape;
701 % fa - scalene triangle:
702 % for stem up: (0,h/2) -- (w,h/2) -- (w,-h/2) -- cycle;
703 % for stem down: (w,-h/2) -- (0,1h/2) -- (0,h/2) -- cycle;
704 % (one is a 180 degree rotation of the other)
705 % stem attachment: (doesn't much matter)
707 save fashape; path fashape;
708 fashape = (-1,1)--(1,1)--(1,-1)--cycle;
710 fet_beginchar("Whole fahead", "0fa", "wholefahead")
711 save a_b, ai_a, bi_b, dx, dy, noteshape, noteishape;
712 path noteshape, noteishape;
714 noteishape = fashape;
719 draw_solfa_note_shape;
722 fet_beginchar("Half stemup fahead", "1fau", "halffauhead")
723 save a_b, ai_a, bi_b, dx, dy, noteshape, noteishape;
724 path noteshape, noteishape;
726 noteishape = fashape;
731 draw_solfa_note_shape;
734 fet_beginchar("Quart stemup fahead", "2fau", "fauhead")
740 draw_solfa_quarter_note_shape;
743 fet_beginchar("Half stemdn fahead", "1fad", "halffadhead")
744 save a_b, ai_a, bi_b, dx, dy, noteshape, noteishape;
745 path noteshape, noteishape;
746 noteshape = fashape rotated 180;
747 noteishape = fashape rotated 180;
752 draw_solfa_note_shape;
755 fet_beginchar("Quart stemdn fahead", "2fad", "fadhead")
760 noteshape = fashape rotated 180;
761 draw_solfa_quarter_note_shape;
765 % sol - oval ... the standard "round" note
767 % la - rectangle: (0,h/2)--(w,h.2)--(w,-h/2)--(0,-h/2)--cycle;
768 % stem attachment: (doesn't much matter)
769 save lashape; path lashape;
770 lashape = (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle;
772 fet_beginchar("Whole lahead", "0la", "wholelahead")
773 save a_b, ai_a, bi_b, dx, dy, noteshape, noteishape;
774 path noteshape, noteishape;
776 noteishape = lashape;
781 draw_solfa_note_shape;
784 fet_beginchar("Half lahead", "1la", "halflahead")
785 save a_b, ai_a, bi_b, dx, dy, noteshape, noteishape;
786 path noteshape, noteishape;
788 noteishape = lashape;
793 draw_solfa_note_shape;
796 fet_beginchar("Quart lahead", "2la", "lahead")
802 draw_solfa_quarter_note_shape;
806 % ti - an "icecream cone" with about 2/3 of
807 % the height in the cone and only 1/3 in the curved top:
808 % (0,h/6)--(w/2,-h/2)--(w,h/6)..(w/2,h/2)..cycle;
809 % stem attachment: h/6
810 save tishape; path tishape;
811 tishape = (0,-1)--(-1,0.3)..(0,1)..(1,0.3)--cycle;
813 fet_beginchar("Whole tihead", "0ti", "wholetihead")
814 save a_b, ai_a, bi_b, dx, dy, noteshape, noteishape;
815 path noteshape, noteishape;
817 noteishape = tishape;
822 draw_solfa_note_shape;
825 fet_beginchar("Half tihead", "1ti", "halftihead")
826 save a_b, ai_a, bi_b, dx, dy, noteshape, noteishape;
827 path noteshape, noteishape;
829 noteishape = tishape;
834 draw_solfa_note_shape;
837 fet_beginchar("Quart tihead", "2ti", "tihead")
843 draw_solfa_quarter_note_shape;
848 fet_endgroup("noteheads");
852 % we derive black_notehead_width# from the quarter head,
853 % so we have to define black_notehead_width (pixel qty)
854 % after the black_notehead_width# itself. Let's keep it outside the group as well.
856 define_pixels(black_notehead_width);