%  -*-Fundamental-*-
% feta-bolletjes.mf --  implement noteheads
% 
% source file of LilyPond's pretty-but-neat music font
% 
% (c) 1997--2001 Jan Nieuwenhuizen <janneke@gnu.org>
% & Han-Wen Nienhuys <hanwen@cs.uu.nl>
% 


% 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);


%%%%%%%%
%
%
%
% MENSURAL NOTATION
%
%
%
brevis_wid# := 2 staff_space#;

def draw_brevis(expr brevwid) =
	save beamheight, head_width;
	save holeheight, stem_width;
	save serif_size, serif_protrude;

	head_width# = brevwid;
	holeheight = 3 stafflinethickness;
	stem_width = 1.4 stafflinethickness;


	define_pixels(head_width);
	set_char_box(0, head_width#, noteheight#/2, noteheight#/2);
	
	2 beamheight + holeheight = noteheight;
	serif_size = (holeheight - stafflinethickness)/2;
	serif_protrude = 1.5 serif_size;
	penpos1(stem_width, 0);
	penpos2(stem_width, 0);
	penpos3(beamheight, 90);
	penpos4(beamheight, 90);
	penpos5(stem_width, 180);

	z1l = (0, 0);
	z2l = (0, -stafflinethickness/2);
	z3r = z2r + serif_size *(1,-1);
	y4r = y3r;
	x4r = head_width/2;
	z5l = z3l + (-serif_size, -serif_protrude);

	penlabels(1,2,3,4, 5);
	fill z1r -- z1l -- z5r{down} .. z5l{up} .. z3l{right}
		-- z4l -- z4r -- z3r{left} .. z2r{up} -- cycle;

	addto currentpicture also currentpicture yscaled -1;
	show z4r; show z4l;
	addto currentpicture also currentpicture 
		shifted (-x4r,0) xscaled -1 shifted (x4l,0);

enddef;


%
% Some sources (eg Musix/OpusTeX think that the appendage should be on
% the left, some say right. Right wins democratically.
%
def draw_longa (expr wid) =
	draw_brevis(wid);
	save theta;

	x7r = head_width;
	y7 = y5;
%	z7 = z5;
	z6 - z7 = (stem_width/2, -staff_space);
	theta = angle(z6-z7)+ 90;
	penpos7(stem_width, theta);
	penpos6(1.2 stem_width, theta);
	
	fill z7r .. z6r{z6-z7} .. {z7-z6} z6l -- z7l -- cycle;
	penlabels(6,7);
enddef;

%
% En wij presenteren U: de opvolgster van Emily
%
% (ze is wel breed)
% 
fet_beginchar("Maxima notehead", "-3mensural", "mensuralmaximahead");
	draw_longa (1.3 brevis_wid#)
fet_endchar;

fet_beginchar("Longa notehead", "-2mensural", "mensurallongahead");
	draw_longa (brevis_wid#)
fet_endchar;

fet_beginchar("Brevis notehead", "-1mensural", "mensuralbrevishead")
	draw_brevis(brevis_wid#);
fet_endchar;

def draw_mensural_black_head (expr wid) =
	save head_width;
	head_width# = wid;
	set_char_box (0, head_width#, noteheight#/2, noteheight#/2);


	y3 = y1 =0;
	x2 = x4 = (x1 + x3) /2;
	define_pixels (head_width);
	pickup pencircle scaled blot_diameter;
	top y2 = h;
	bot y4 = -d;
	lft x1 = 0;
	rt x3 = w;

	filldraw z1 -- z2 -- z3 -- z4 -- cycle;
enddef;

def draw_mensural_open_head (expr wid)=
	draw_mensural_black_head (wid);
	save diamNW, diamSW;
	diamNW = length (z2 - z1) + blot_diameter;
	diamSW = length (z4 - z1) + blot_diameter;
	
	save hole_widthNW, hole_widthSW;
	hole_widthNW = 0.34 diamNW ;
	hole_widthSW + 2.6 stafflinethickness = diamSW;

	(z7 + z5)/2 = (w/2, 0);
	(z8 + z6)/2 = (w/2, 0);
	(z6 - z5) = hole_widthNW * unitvector (z2 - z1);
	(z7 - z6) = hole_widthSW * unitvector (z4 - z1);

	labels (1,2,3,4,5,6,7,8);

	unfill z5 -- z6 -- z7 -- z8 --cycle;
enddef;

fet_beginchar("Mensural open head","0mensural","mensuralminimhead")
	draw_mensural_open_head (staff_space#);
fet_endchar;

fet_beginchar("Mensural open head","1mensural","mensuralsemiminimhead")
	draw_mensural_open_head (staff_space#);
fet_endchar;

fet_beginchar("Mensural black head","2mensural","fusahead")
	draw_mensural_black_head (staff_space#);
fet_endchar;


%%%%%%%%%%%%
%
%
% ledger (leger) lines
%
fet_beginchar("Ledger ending", "ledgerending", "ledgerending")
set_char_box (5/2 ledgerlinethickness#, 5/2 ledgerlinethickness#,
  		ledgerlinethickness#/2,ledgerlinethickness#/2);
	pickup pencircle scaled 1.3 blot_diameter;

	rt x2 = w;
	lft x1 = -b;
	x3 = x2;
	bot y1 = -d;
	y2 = y1;

	top y3 = h;
	y4 = y3;
	x4 = x1;

	filldraw z1 --- z2 --- z3 --- z4 --- cycle ;
fet_endchar;



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
%
%
%
% 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;


% 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
		fill black;
		unfill white;

		
	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 z1 -- z2;
	draw z3 -- z4;
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;
	ai_a:=0.850; % jcn
	% ai_bi:=3.14;
	ai_bi:=3.30; % jcn
	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;
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 triangle; path triangle;
triangle = (-sqrt3/4,-1/2) -- (0,1) -- (sqrt3/4,-1/2) -- cycle;

fet_beginchar("Whole trianglehead", "0triangle", "wholetrianglehead")
	set_char_box(0, 2(noteheight#+stafflinethickness#)/sqrt3*7/8,
	  (noteheight#+stafflinethickness#)/2,(noteheight#+stafflinethickness#)/2);
	fill triangle scaled (7h/6) shifted (w/2,-h/6);
	unfill triangle scaled 0.72h shifted (w/2,-h/6);
fet_endchar;
fet_beginchar("Half trianglehead", "1triangle", "halftrianglehead")
	thick := 1.2stafflinethickness;
	set_char_box(0, 2noteheight#/sqrt3*7/8,noteheight#/2,noteheight#/2);
	fill triangle scaled (7h/6) shifted (w/2,-h/6);
	unfill triangle scaled 0.7h shifted (w/2,-h/6);
fet_endchar;
fet_beginchar("Quart trianglehead", "2triangle", "trianglehead")
	thick := 1.2stafflinethickness;
	set_char_box(0, 2noteheight#/sqrt3*7/8,noteheight#/2,noteheight#/2);
	fill triangle scaled (7h/6) shifted (w/2,-h/6);
fet_endchar;

%%% Editable values:
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:
slxt := sqrt(slt*slt+(slt/slope)*(slt/slope)); % Width of hor. pen - with thanks to Pythagoras
slw := slh/slope; % width of sloping part of slash:

% is this really nessesary? -rz
fac# := staff_space#/staff_space;
slt# := fac#*slt;
slh# := fac#*slh;
sxa# := fac#*sxa;
slxt# := fac#*slxt;
slw# := fac#*slw;

def draw_slash(expr hwid) =
	wid# := slw#+2slxt#+hwid*fac#;
	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#;
	hei# := noteheight#+stafflinethickness#;
	set_char_box(0, wid#,hei#/2,hei#/2);
	cthick := 1.2stafflinethickness;
	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);
