% Feta (not the Font-En-Tja) music font -- draw accordion symbols
% This file is part of LilyPond, the GNU music typesetter.
%
% Copyright (C) 1998--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
%
% The LilyPond font is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version, or you can redistribute it under
% the SIL Open Font License.
%
% LilyPond is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.

fet_begingroup ("accordion");

%
% These dimensions are the same for all register symbols.
% The different symbols should calculate their other dimensions from them.
%

accreg_dot_size# := .5 staff_space#;
accreg_linethickness# := 1.3 stafflinethickness#;
accreg_lh# := 1.0 staff_space#;

define_pixels (accreg_dot_size, accreg_linethickness, accreg_lh);


fet_beginchar ("accordion register discant", "discant")
	save r, pat, lh, lt;
	path pat;

	r# = 3/2 accreg_lh#;
	define_pixels (r);

	set_char_box (r# + accreg_linethickness# / 2,
		      r# + accreg_linethickness# / 2,
		      0.7 accreg_linethickness# / 2,
		      2 r# + 0.7 accreg_linethickness# / 2);

	lh = vround (2/3 r);
	lt = vround (0.7 accreg_linethickness);
	d := vround (0.7 accreg_linethickness / 2);
	h := 3 lh + lt - d;
	b := w := (3 lh + hround accreg_linethickness) / 2;

	penpos1 (hround accreg_linethickness, 0);
	penpos2 (lt, 90);
	penpos3 (hround accreg_linethickness, 180);
	penpos4 (lt, 270);

	z1r = (w, 0.5 [-d, h]);
	z2r = (0, h);
	z3r = (-b, 0.5 [-d, h]);
	z4r = (0, -d);

	penlabels (1, 2, 3, 4);

	% mf doesn't handle pixel dropouts in outline objects, so we use
	% `draw' if not called by mpost
	if known miterlimit:
		fill z1r
		     .. z2r
		     .. z3r
		     .. z4r
		     .. cycle;
		unfill z1l
		       .. z2l
		       .. z3l
		       .. z4l
		       .. cycle;
	else:
		pickup pencircle xscaled accreg_linethickness yscaled lt;
		draw z1
		     .. z2
		     .. z3
		     .. z4
		     .. cycle;
	fi;

	pat := z4{right}
	       .. z1{up}
	       .. {left}z2;

	pickup penrazor scaled lt rotated 90;

	top z5 = pat intersectionpoint ((0, lh + lt - d) -- (w, lh + lt - d));
	z6 = z5 xscaled -1;
	bot z7 = pat intersectionpoint ((0, 2 lh - d) -- (w, 2 lh - d));
	z8 = z7 xscaled -1;

	labels (5, 6, 7, 8);

	draw z5
	     -- z6;
	draw z7
	     -- z8;
fet_endchar;


fet_beginchar ("accordion register dot", "dot")
	set_char_box (accreg_dot_size# / 2, accreg_dot_size# / 2,
		      accreg_dot_size# / 2, accreg_dot_size# / 2);

	pickup pencircle scaled accreg_dot_size;

	rt x0 = hround (accreg_dot_size / 2);
	top y0 = vround (accreg_dot_size / 2);

	drawdot z0;
fet_endchar;


fet_beginchar ("accordion register freebass", "freebass")
	save r, lh, lt;

	r# = accreg_lh#;
	define_pixels (r);

	set_char_box (r# + accreg_linethickness# / 2,
		      r# + accreg_linethickness# / 2,
		      0.7 accreg_linethickness# / 2,
		      2 r# + 0.7 accreg_linethickness# / 2);

	lh = vround r;
	lt = vround (0.7 accreg_linethickness);
	d := vround (0.7 accreg_linethickness / 2);
	h := 2 lh + lt - d;
	b := w := (2 lh + hround accreg_linethickness) / 2;

	penpos1 (hround accreg_linethickness, 0);
	penpos2 (lt, 90);
	penpos3 (accreg_linethickness, 180);
	penpos4 (lt, 270);

	z1r = (w, 0.5 [-d, h]);
	z2r = (0, h);
	z3r = (-b, 0.5 [-d, h]);
	z4r = (0, -d);

	penlabels (1, 2, 3, 4);

	% mf doesn't handle pixel dropouts in outline objects, so we use
	% `draw' if not called by mpost
	if known miterlimit:
		fill z1r
		     .. z2r
		     .. z3r
		     .. z4r
		     .. cycle;
		unfill z1l
		       .. z2l
		       .. z3l
		       .. z4l
		       .. cycle;
	else:
		pickup pencircle xscaled accreg_linethickness yscaled lt;
		draw z1
		     .. z2
		     .. z3
		     .. z4
		     .. cycle;
	fi;

	pickup penrazor scaled lt rotated 90;

	draw z1
	     -- z3;
fet_endchar;


fet_beginchar ("accordion register stdbass", "stdbass")
	save r, p, lh, lt;
	path pat;

	r# = 2 accreg_lh#;
	define_pixels (r);

	set_char_box (r# + accreg_linethickness# / 2,
		      r# + accreg_linethickness# / 2,
		      0.7 accreg_linethickness# / 2,
		      2 r# + 0.7 accreg_linethickness# / 2);

	lh = vround (1/2 r);
	lt = vround (0.7 accreg_linethickness);
	d := vround (0.7 accreg_linethickness / 2);
	h := 4 lh + lt - d;
	b := w := (4 lh + hround accreg_linethickness) / 2;

	penpos1 (hround accreg_linethickness, 0);
	penpos2 (lt, 90);
	penpos3 (hround accreg_linethickness, 180);
	penpos4 (lt, 270);

	z1r = (w, 0.5 [-d, h]);
	z2r = (0, h);
	z3r = (-b, 0.5 [-d, h]);
	z4r = (0, -d);

	penlabels (1, 2, 3, 4);

	% mf doesn't handle pixel dropouts in outline objects, so we use
	% `draw' if not called by mpost
	if known miterlimit:
		fill z1r
		     .. z2r
		     .. z3r
		     .. z4r
		     .. cycle;
		unfill z1l
		       .. z2l
		       .. z3l
		       .. z4l
		       .. cycle;
	else:
		pickup pencircle xscaled accreg_linethickness yscaled lt;
		draw z1
		     .. z2
		     .. z3
		     .. z4
		     .. cycle;
	fi;

	pat := z4{right}
	       .. z1{up}
	       .. {left}z2;

	pickup penrazor scaled lt rotated 90;

	top z5 = pat intersectionpoint ((0, lh + lt - d) -- (w, lh + lt - d));
	z6 = z5 xscaled -1;
	bot z7 = pat intersectionpoint ((0, 3 lh - d) -- (w, 3 lh - d));
	z8 = z7 xscaled -1;

	labels (5, 6, 7, 8);

	draw z1
	     -- z3;
	draw z5
	     -- z6;
	draw z7
	     -- z8;
fet_endchar;


fet_beginchar ("accordion register bayanbass", "bayanbass")
	save lh, lt;

	lh = vround accreg_lh;
	lt = vround accreg_linethickness;

	set_char_box (accreg_lh# + accreg_linethickness# / 2,
		      accreg_lh# + accreg_linethickness# / 2,
		      accreg_linethickness# / 2,
		      3 accreg_lh# + accreg_linethickness# / 2);

	d := vround (accreg_linethickness# / 2);
	h := 3 lh + lt - d;

	draw_rounded_block ((-w, -d), (-w + lt, h), lt);
	draw_rounded_block ((w - lt, -d), (w, h), lt);

	pickup penrazor scaled lt rotated 90;

	bot z1 = (-w + lt / 2, -d);
	bot z2 = (-w + lt / 2, lh - d);
	bot z3 = (-w + lt / 2, 2 lh - d);
	bot z4 = (-w + lt / 2, 3 lh - d);

	bot z5 = (w - lt / 2, -d);
	bot z6 = (w - lt / 2, lh - d);
	bot z7 = (w - lt / 2, 2 lh - d);
	bot z8 = (w - lt / 2, 3 lh - d);

	draw z1
	     -- z5;
	draw z2
	     -- z6;
	draw z3
	     -- z7;
	draw z4
	     -- z8;
fet_endchar;


def def_B (expr w, h) =
	pickup pencircle scaled 0.15 linethickness;

	penpos10 (thin, -90);
	penpos11 (thin, -90);
	penpos12 (thick, 0);
	penpos13 (thin, 90);
	penpos14 (thin, 90);

	penpos15 (thick, 180);
	penpos16 (thin, -90);
	penpos17 (thin, -90);
	penpos18 (thick, 0);
	penpos19 (thick, 0);

	z10 = (0, 0);
	z11 = (cOne * w, 0);
	z12 = (w, .5 mb * h);
	z13 = (cTwo * w, mb * h);
	z14 = (2 thick, mb * h);
	z15 = (.94 w, h - .5 mt * h);
	z16 = z13 + (0, mt * h);
	z17 = (0, h);
	z18 = (1.5 thick, 0);
	z19 = (1.5 thick, h);
enddef;


def def_S (expr w, h) =
	pickup pencircle scaled 0.03 linethickness;

	penpos1 (thin, 180);
	penpos2 (thin, -90);
	penpos3 (thick, 0);
	penpos4 (.5 thick, 90);
	penpos5 (thick, 0);
	penpos6 (thin, -90);
	penpos7 (thin, 180);
	penpos8 (thin, 180);
	penpos9 (thin, 0);

	z1 = (0, hs);
	z2 = (w / 2, 0);
	z3 = (w - .5 thick, .5 mb * h);
	z4 = (w / 2, mb * h);
	z5 = (.5 thick, h - .5 mt * h);
	z6 = (w / 2, h);
	z7 = (w, h - hs);
	z8 = (0, y2r);
	z9 = (w, y6l);

	path bue, bueoverst;

	bue := z2{left}
	       .. z1{up};

	t := xpart (bue intersectiontimes (z8l -- z7l));

	bueoverst := z6{right}
		     .. z7{down};
enddef;


def def_some_vars =
	save hs, mb, mt, thin, thick, height, width, cOne, cTwo;
	save bx, hx;

	width = .8 (4 staff_space);
	height = 2.4 staff_space;
	% URG.  smaller sizes should be wider and fatter
	% thin = 0.05 staff_space;
	% thick = 0.2 staff_space;

	4 hx + bx = 1.15;
	10 hx + bx = 1;
	fatten := designsize * hx + bx * 1.2;
	thick := 0.2 staff_space * fatten;

	% urg: mustn't ever go thinner than blot!
	thin# := blot_diameter#;
	define_pixels (thin);

	hs = 0.4 staff_space;
	mb = .53;
	mt = .47;
	cOne = 0.65;
	cTwo = 0.60;
enddef;


fet_beginchar ("accordion oldEE", "oldEE")
	save r, pp, ir, lh, lt, stroke_width;

	r# = staff_space#;
	define_pixels (r);

	lr = .4 staff_space - linethickness;
	ir = .6 staff_space;
	stroke_width = .05 staff_space + .5 linethickness;

	set_char_box (r# + accreg_linethickness# / 2,
		      r# + accreg_linethickness# / 2,
		      0, 2 r# + 0.7 accreg_linethickness#);

	z1 = (0, 0);
	z2 = (0, ir);
	z3 = (0, -ir);

	penpos1 (blot_diameter, 0);
	penpos2 (stroke_width + blot_diameter, 0);
	penpos3 (stroke_width + blot_diameter, 0);

	pickup pencircle scaled (lr + blot_diameter);

	for pp := 0 step 45 until 135:
		drawdot z2 rotated pp;
		drawdot z3 rotated pp;

		penstroke (z2e
			   -- z1e
			   -- z3e) rotated pp;
	endfor;

	pickup pencircle scaled lr;

	drawdot (0, 0);

	currentpicture := currentpicture shifted (0, h / 2);

	lh = vround (2 r);
	lt = vround (0.7 accreg_linethickness);

	h := lh + lt;
	b := w := (lh + hround accreg_linethickness) / 2;

	penpos10 (hround accreg_linethickness, 0);
	penpos11 (lt, 90);
	penpos12 (hround accreg_linethickness, 180);
	penpos13 (lt, 270);

	z10r = (w, h / 2);
	z11r = (0, h);
	z12r = (-b, h / 2);
	z13r = (0, 0);

	% penlabels (1, 2, 10, 11, 12, 13);

	% mf doesn't handle pixel dropouts in outline objects, so we use
	% `draw' if not called by mpost
	if known miterlimit:
		fill z10r
		     .. z11r
		     .. z12r
		     .. z13r
		     .. cycle;
		unfill z10l
		       .. z11l
		       .. z12l
		       .. z13l
		       .. cycle;
	else:
		pickup pencircle xscaled accreg_linethickness yscaled lt;
		draw z10
		     .. z11
		     .. z12
		     .. z13
		     .. cycle;
	fi;
fet_endchar;


fet_beginchar ("accordion push", "push");
	save width, height;

	height# := 2.0 staff_space# + 3.0 stafflinethickness#;
	width# := 0.4 height#;

	define_pixels(height, width);

	save linewidth;

	linewidth# := stafflinethickness# + .05 staff_space#;
	define_whole_blacker_pixels (linewidth);

	set_char_box (width#, 0,
	              0, height#);

	pickup pencircle scaled linewidth;

	lft x1 = -width;
	top y1 = height;

	rt x2 = 0;
	y2 = 0.5 * (y1 + y3);

	x3 = x1;
	bot y3 = 0;

	save nw_offset, ne_offset;
	pair nw_offset, ne_offset;
	save sw_offset, se_offset, line_radius;
	pair sw_offset, se_offset;

	line_radius := linewidth / 2;
	nw_offset := line_radius * unitvector (z1 - z2);
	ne_offset := nw_offset rotated -90;
	sw_offset := line_radius * unitvector (z3 - z2);
	se_offset := sw_offset rotated 90;

	z4 = ((z1 - ne_offset)
	     -- (z2 - ne_offset))
	     intersectionpoint
	     ((z2 - se_offset)
	     -- (z3 - se_offset));

	fill z1 + ne_offset
	     -- z2 + ne_offset
	     .. rt z2 {down}
	     .. z2 + se_offset
	     -- z3 + se_offset
	     .. z3 + sw_offset {- se_offset}
	     .. z3 - se_offset
	     -- z4
	     -- z1 - ne_offset
	     .. z1 + nw_offset {ne_offset}
	     .. cycle;
fet_endchar;


fet_beginchar ("accordion pull", "pull");
	save width, height;

	height# := 2.0 staff_space# + 3.0 stafflinethickness#;
	width# := 0.4 height#;

	define_pixels(height, width);

	save linewidth;

	linewidth# := stafflinethickness# + .05 staff_space#;
	define_whole_blacker_pixels (linewidth);

	set_char_box (width# - linewidth#, linewidth#,
	              0, height#);

	pickup pencircle scaled linewidth;

	save penradius;
	penradius := linewidth / 2;

	rt x1 = linewidth;
	bot y1 = 0;

        x2 = x1;
	top y2 = height;

	lft x3= -width + linewidth;
	y3 = y2;

	x4 = x3;
	y4 = y2 - linewidth;

	x5 = x1;
	y5 = y4;

	fill z1 + penradius * right {up}
	     -- z2 + penradius * right {up}
	     .. z2 + penradius * up {left}
	     -- z3 + penradius * up {left}
	     .. z3 + penradius * left {down}
	     -- z4 + penradius * left {down}
	     .. z4 + penradius * down {right}
	     -- z5 + penradius * (down + left)
	     -- z1 + penradius * left {down}
	     .. z1 + penradius * down {right}
	     .. cycle;
fet_endchar;

fet_endgroup ("accordion");
