% -*-Fundamental-*- % feta-bolletjes.mf -- implement noteheads % % source file of LilyPond's pretty-but-neat music font % % (c) 1997--2003 Jan Nieuwenhuizen % & Han-Wen Nienhuys % & Juergen Reuter % % most beautiful noteheads are pronounced, not circular, % and not even symmetric. % These examples are inspired by [Wanske], see literature list save black_notehead_width; numeric black_notehead_width; fet_begingroup("noteheads"); noteheight#:=staff_space#+ (1 + overdone_heads) *stafflinethickness#; define_pixels(noteheight); % %%% TODO: Document these! % % setup user vars def setup_notehead_vars = save a_b,err_y_a,tilt,superness; save ai_a,ai_bi,err_y_ai,err_x_bi,inner_tilt,inner_superness; save b_h,a_w; enddef; % setup addititional vars and calc them def notehead_calc = save a,beta,ai,bi, ht, wd; ht# =noteheight#; 2beta#=ht#*b_h; a# = beta#*a_b; wd# = 2a# / a_w; ai# = a# * ai_a; bi# = ai#/ai_bi; define_pixels(a,beta); define_pixels(ai,bi); set_char_box(0, wd#, .5 ht#, .5 ht#); enddef; % a: x diameter % b: y diameter % err_x: drift of y axis at top % err_y: drift of x axis at right def distorted_ellipse(expr a,b,err_y,err_x,super) = superellipse((a,err_x),(-err_y,b),(-a,-err_x),(err_y,-b),super); enddef; % draw the outer and inner ellipse. def notehead_draw = path black,white; black=distorted_ellipse(a,beta,a*err_y_a,0,superness); white=distorted_ellipse(ai,bi,ai*err_y_ai,bi*err_x_bi,inner_superness); if test > 1: %fixme save x; x1=-x3=a; x2=x4=0; y1=y3=0; y2=-y4=b; penlabels(1,2,3,4); test_grid; else: black:=black rotated tilt; black:=black shifted (w/2,0); white:=white rotated inner_tilt; white:=white shifted (w/2,0); fi if test = 1: pickup pencircle scaled 1; draw black; draw white; else: fill black; unfill white; fi enddef; def draw_whole_head = setup_notehead_vars; a_b:=1.80; err_y_a:=0; % no slant tilt:=0; superness:=0.707; ai_a:=0.508; % ai_bi:=1.23; ai_bi:=1.30; % jcn % err_y_ai:=0.0938; % err_x_bi:=0; err_y_ai:=0; err_x_bi:=0.115; % inner_tilt:=135; inner_tilt:=125; % jcn % inner_superness:=0.69; inner_superness:=0.68; % jcn b_h:=1; %no rotate-> no height correction a_w:=1; % no rotate-> no width correction notehead_calc; whole_notehead_width# := wd#; notehead_draw; enddef; % % dimensions aren't entirely right. % fet_beginchar ("Brevis notehead", "-1", "brevishead"); save stemthick, fudge; define_pixels (stemthick); fudge = blot_diameter /2; stemthick# = 2 stafflinethickness#; draw_whole_head; pickup pencircle scaled stemthick; bot y1 = -d; top y2 = h; rt x1 - fudge = 0; x1 = x2; fudge + lft x3 = w; x4 = x3; y4 = y2; y3 = y1; draw_gridline(z1,z2,stemthick); draw_gridline(z3,z4,stemthick); fet_endchar; % whole note % Wanske, p.38 fet_beginchar("Whole notehead", "0", "wholehead") draw_whole_head; fet_endchar; % half note % Wanske, p.39 fet_beginchar("Half notehead", "1", "halfhead") setup_notehead_vars; % a_b:=1.49; % after text a_b:=1.50; % after drawing err_y_a:=0.157; tilt:=34; % superness:=0.66; superness:=0.67; % jcn % ai_a:=0.863; % was 0.85 % set to 0.83 to avoid stem entering white part. ai_a:=0.830; % ai_bi:=3.14; ai_bi:=3.25; err_y_ai:=0; err_x_bi:=-0.12; inner_tilt:=tilt; inner_superness:=0.80; b_h:=0.935; a_w:=1.12; notehead_calc; half_notehead_width# := wd#; notehead_draw; define_pixels (wd); if test = 1: pickup penrazor scaled stemthickness; draw (.5 stemthickness, -2 staff_space) .. (.5 stemthickness, - wd * (ypart dir (inner_tilt - 10)) /2); fi; fet_endchar; % quarter note % Wanske p.38 fet_beginchar("Quart notehead", "2", "quarthead") setup_notehead_vars; % a_b:=1.57; % after text a_b:=1.54; % after drawing err_y_a:=0.044; tilt:=32; superness:=0.707; ai_a:=0; ai_bi:=1; err_y_ai:=0; err_x_bi:=0; inner_tilt:=0; inner_superness:=0.707; b_h:=0.85; a_w:=1.09; notehead_calc; black_notehead_width# := wd#; notehead_draw; fet_endchar; % whole note % Wanske, p.38 fet_beginchar("Whole diamondhead", "0diamond", "wholediamondhead") setup_notehead_vars; a_b:=1.80; err_y_a:=0; % no slant tilt:=0; superness:=0.495; ai_a:=0.350; % ai_bi:=1.23; ai_bi:=1.30; % jcn % err_y_ai:=0.0938; % err_x_bi:=0; err_y_ai:=0; err_x_bi:=0.115; % inner_tilt:=135; inner_tilt:=125; % jcn % inner_superness:=0.69; inner_superness:=0.6; % jcn b_h:=1; %no rotate-> no height correction a_w:=1; % no rotate-> no width correction notehead_calc; whole_notehead_width# := wd#; notehead_draw; fet_endchar; % half note % Wanske, p.39 fet_beginchar("Half diamondhead", "1diamond", "halfdiamondhead") setup_notehead_vars; a_b := 1.50; % after drawing err_y_a:=0.157; tilt:=34; superness:=0.49; % jcn ai_a:=0.550; % jcn ai_bi:=3.30; % jcn err_y_ai:=0; err_x_bi:=-0.12; inner_tilt:=tilt; inner_superness:=0.80; b_h:= 1.03; a_w:= 1.2; notehead_calc; half_notehead_width# := wd#; notehead_draw; fet_endchar; % quarter note % Wanske p.38 fet_beginchar("Quart diamondhead", "2diamond", "diamondhead") set_char_box(0, black_notehead_width#, noteheight#/2, noteheight#/2); save a_b,err_y_a,tilt,superness; save b_h,a_w; save a,beta,ai,bi, ht, wd; a_b:= 1.8; err_y_a:=-0.044; b_h:=0.90; a_w:=1.1; tilt:=35; superness:=0.495; ht# =noteheight#; 2beta#=ht#*b_h; a# = beta#*a_b; define_pixels(a,beta); black := distorted_ellipse(.72 noteheight, .45 noteheight, -.2 noteheight , 0, superness) % beta,a*err_y_a,0,superness); black:=black rotated tilt; black:=black shifted (w/2,0); fill black; fet_endchar; save pent; pen_thick# = 2stafflinethickness#; define_pixels(pen_thick); begingroup; def def_triangle_old = save triangle,kern; path triangle; kern = 1/3(x2-x1); z2 = z1 rotated 120; z3 = z1 rotated 240; z12 = caveness[.5[z1,z2],z3]; z23 = z12 rotated 120; z31 = z12 rotated 240; triangle = z1 .. z12 .. z2 .. z2 .. z23 .. z3 .. z3 .. z31 .. z1 .. cycle; triangle := triangle shifted (-x1+pent/2-kern,0) xscaled xs; pickup pencircle scaled pent xscaled xs; hei = max(y1,-y2)+pent/2; %set_char_box(-kern*xs*fac, ((x3-x1)*fac+pent#)*xs,hei*fac,hei*fac); set_char_box(0, ((x3-x1-kern)*fac+pent#)*xs,hei*fac,hei*fac); enddef; def def_triangle = save triangle,kern; path triangle; save left_point, height, width; pair exact_left_point; exact_left_point := llap# * dir (90 + tilt); height# = max (ypart exact_left_point, -ypart (exact_left_point rotated 120)) + pen_thick#/2; kern# = 1/3 xpart (exact_left_point - (exact_left_point rotated 120)); width# = xpart (-exact_left_point + (exact_left_point rotated 240)); define_pixels (kern); z1 = (hround_pixels (xpart exact_left_point), vround_pixels (ypart exact_left_point)); z2 = z1 rotated 120; z3 = z1 rotated 240; z12 = caveness[.5[z1,z2],z3]; z23 = z12 rotated 120; z31 = z12 rotated 240; triangle = z1 .. z12 .. z2 .. z2 .. z23 .. z3 .. z3 .. z31 .. z1 .. cycle; triangle := triangle shifted (-x1+pen_thick/2-kern,0) xscaled xs; pickup pencircle scaled pen_thick xscaled xs; % labels(1,2,12,23,31,3); set_char_box(0, width# - kern#+ pen_thick#, height#, height#); enddef; fet_beginchar("Whole trianglehead", "0triangle", "wholetrianglehead") save hei,xs; save llap; save tilt; tilt = 40; llap# = 3/4noteheight#; xs = 1.5; caveness:=0.1; def_triangle; draw triangle; fet_endchar; fet_beginchar("Half trianglehead", "1triangle", "halftrianglehead") save hei,xs; save llap; save tilt; tilt = 40; llap# = 2/3noteheight#; xs = 1.2; caveness:=0.1; def_triangle; draw triangle; fet_endchar; fet_beginchar("Quart trianglehead", "2triangle", "trianglehead") save hei,xs; save llap; save tilt; tilt = 40; llap# = 2/3noteheight#; xs = 1.0; caveness:=0.1; def_triangle; filldraw triangle; fet_endchar; endgroup; %%% Editable values: slash_slope := 1.7; % slope of slash. From scm/grob-description.scm. How to auto-copy? slt# := 2/3*0.48staff_space#; % thickness of lines. quarter notes get 1.5slt width. slh# := 2staff_space#; % height of char. %%% Calculated values: sxa# := 0; % how much the char exceeds the boundingbox horizontally: % Width of hor. pen - with thanks to Pythagoras slxt# := sqrt(slt#*slt#+(slt#/slash_slope)*(slt#/slash_slope)); slw# := slh#/slash_slope; % width of sloping part of slash: define_pixels(slt,slh,sxa,slxt,slw); % % % UUGGGH! FIXME -- get rid of those sharp corners. % % % def draw_slash(expr hwid_hash) = wid# := slw#+2slxt#+hwid_hash; set_char_box(0,wid#-2sxa#,slh#/2,slh#/2); define_pixels (wid#); pickup penrazor scaled slxt; draw (-b+slxt/2-sxa,-d) -- (-b+slxt/2+slw-sxa,h); draw (w-slxt/2-slw+sxa,-d) -- (w-slxt/2+sxa,h); pickup penrazor scaled slt rotated 90; draw (-b+slxt-sxa,-d+slt/2) -- (w-slw+sxa,-d+slt/2); draw (-b+slw-sxa,h-slt/2) -- (w-slxt+sxa,h-slt/2); enddef; fet_beginchar("Whole slashhead","0slash","wholeslashhead") draw_slash(staff_space#); fet_endchar; fet_beginchar("Half slashhead","1slash","halfslashhead") draw_slash(0.6staff_space#); fet_endchar; fet_beginchar("Quart slashhead","2slash","quartslashhead") draw_slash(-slxt#/2); fet_endchar; % thick is the distance between the two parallel lines in the cross (distance between centres of lines) def draw_cross(expr thick) = pent := 1.2stafflinethickness; pickup pencircle scaled pent; % alfa is the slant of the lines (i.e. 1 means 45 degrees) alfa := (2h-pent)/(w-pent); % llen is the length of the little outer lines % llen = thick / sin(2atan(alfa)) llen := thick/(ypart(dir(2angle(1,alfa)))); xa := llen/sqrt(1+alfa**2); ya := xa*alfa; xl := w/2-xa-pent/2; yl := h-ya-pent/2; save crz; path crz; crz = (xa,0) -- (xa+xl,yl) -- (xl,yl+ya) -- (0,ya); draw crz shifted(w/2,0); draw crz xscaled -1 shifted(w/2,0); draw crz yscaled -1 shifted(w/2,0); draw crz scaled -1 shifted(w/2,0); enddef; fet_beginchar("Whole Crossed notehead", "0cross", "wholecrossedhead") wid# := black_notehead_width#+4stafflinethickness#; hei# := noteheight#+stafflinethickness#; set_char_box(0, wid#,hei#/2,hei#/2); draw_cross(3.75stafflinethickness); fet_endchar; fet_beginchar("Half Crossed notehead", "1cross", "halfcrossedhead") wid# := black_notehead_width#+2stafflinethickness#; hei# := noteheight#+stafflinethickness#/2; set_char_box(0, wid#,hei#/2,hei#/2); draw_cross(3stafflinethickness); fet_endchar; fet_beginchar("Crossed notehead", "2cross", "crossedhead") wid# := black_notehead_width#; hei# := noteheight#; set_char_box(0, wid#,hei#/2,hei#/2); draw_cross(stafflinethickness/4); fet_endchar; fet_beginchar("X-Circled notehead", "2xcircle", "xcircledhead") wid# := black_notehead_width#*sqrt(sqrt2); hei# := noteheight#*sqrt(sqrt2); set_char_box(0, wid#,hei#/2,hei#/2); cthick := (1.2+1/4)*stafflinethickness; cxr := w/2-cthick/2; cyr := h-cthick/2; pickup pencircle scaled cthick; draw fullcircle xscaled 2cxr yscaled 2cyr shifted (w/2,0); xpos := cxr/sqrt2; ypos := cyr/sqrt2; draw (-xpos+w/2,-ypos) -- (xpos+w/2,ypos); draw (-xpos+w/2,ypos) -- (xpos+w/2,-ypos); fet_endchar; fet_endgroup("noteheads"); define_pixels(black_notehead_width);