-%
-% feta-arrow.mf -- draw arrow heads
-%
-% source file of the GNU LilyPond music typesetter
-%
-% (c) 2005--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
-
-fet_begingroup ("arrowheads");
%
-% To consider: we could put arrow heads at their real Unicode locations.
+% Draw an arrow
%
-
+% * `stemslant' gives the direction of the stem's left boundary
+% (needed for brushed stems, equals "up" for straight stems)
+% * `extend' is used to make the stem longer or shorter (if negative);
+% different kinds of accidentals need different values here
%
-% Set up paths for upper half of arrow head pointing right.
-% CLOSE_PATH is for a closed arrow, OPEN_PATH is for the open arrow.
-% OPEN_TENSION sets the tension for the part which forms the path in
-% OPEN_PATH.
-%
-
-def set_arrow_paths (expr width, height, open_tension, arrowlinethickness) =
- save pat, finalpath;
- save tip_angle_o, tip_angle_c, tip_dir_c, tip_dir_o;
- save indent;
- path pat, open_path, close_path;
- pair tip_dir_o, tip_dir_c;
-
- pickup pencircle scaled arrowlinethickness;
-
- indent = linethickness / 2;
-
- lft x1 = -width;
- x2 = 0;
- top y1 = height;
- y2 = 0;
-
- z4 = z3;
- y5 = 0;
- x5 = x4 + indent;
-
- pat := z1
- ..tension open_tension.. z2{right};
- penpos2 (arrowlinethickness, 90);
- tip_dir_o := direction 0.0 of pat;
- tip_angle_o := angle (tip_dir_o);
- penpos1 (arrowlinethickness, 90 + tip_angle_o);
- z3 = z1;
- penpos3 (arrowlinethickness, tip_angle_o);
-
- open_path := z1r{tip_dir_o}
- .. z2r{right}
- .. z2l{left}
- .. z1l{-tip_dir_o}
- .. z3l
- .. cycle;
-
- pat := z4
- .. z5{down};
- tip_dir_c := direction 0.0 of pat;
- tip_angle_c := angle (tip_dir_c);
- penpos4 (arrowlinethickness, 90+ tip_angle_c);
- penpos5 (arrowlinethickness, 0);
- z6 = z5;
- penpos6 (arrowlinethickness, 90);
-
- close_path := z4l{tip_dir_c}
- .. z5l{down}
- .. z6l{right}
- .. z2l{right}
- .. z2r{left}
- ..tension open_tension.. z1r{-tip_dir_o}
- .. z3l
- .. cycle;
+def draw_arrow (expr attach, stemwidth, stemslant, extend, pointingdown) =
+begingroup;
+ save htip; % tip height
+ save wwing; % wing `radius'
+ save angle_wing_bot, angle_wing_top, angle_tip;
+ save upshift;
+ clearxy;
+
+ wwing := 0.26 stemwidth;
+ htip := staff_space * 0.85 + stafflinethickness - wwing;
+
+ % `flip' is used to reflect the arrow vertically
+ % if arrow points downward
+ transform flip;
+ if pointingdown:
+ flip = identity reflectedabout (origin, right);
+ else:
+ flip = identity;
+ fi;
+
+ z1 = attach shifted (-stemwidth / 2, 0);
+ upshift := max (0, wwing + 0.1 staff_space + extend);
+ z2 = z1 shifted (((unitvector stemslant)
+ scaled upshift) transformed flip);
+
+ z7 = attach shifted ((stemwidth/2),0);
+ z6 = z7 shifted (((unitvector (-xpart stemslant, ypart stemslant))
+ scaled upshift) transformed flip);
+ z2 - z3 = ( 0.38 staff_space, 0.05 htip) transformed flip;
+ z6 - z5 = (-0.38 staff_space, 0.05 htip) transformed flip;
+
+ z4 = attach shifted ((-0.2 stemwidth, upshift + htip)
+ transformed flip);
+ z4'= attach shifted (( 0.2 stemwidth, upshift + htip)
+ transformed flip);
+
+ % `angle_wing_bot' is the angle at which the arc
+ % from z2 to z3a enters z3a
+ % `angle_wing_top' is the angle at which the arc
+ % from z3b to z4 leaves z3b
+ % `angle_tip' is the angle at which the arc
+ % from z4 to z4' leaves z4
+ angle_wing_bot = 30;
+ angle_wing_top = 55;
+ angle_tip = 68;
+
+ z3a = z3 shifted ((((dir angle_wing_bot) rotated -90)
+ scaled wwing) transformed flip);
+ z3b = z3 shifted ((((dir angle_wing_top) rotated 90)
+ scaled wwing) transformed flip);
+
+ z5a = z5 shifted ((((dir (180 - angle_wing_bot)) rotated 90)
+ scaled wwing) transformed flip);
+ z5b = z5 shifted ((((dir (180 - angle_wing_top)) rotated -90)
+ scaled wwing) transformed flip);
+
+ % Draw the arrow
+ pickup pencircle scaled 1;
+ fill z1
+ -- z2{stemslant transformed flip}
+ .. {(-dir angle_wing_bot) transformed flip}z3a
+ .. z3b{(dir angle_wing_top) transformed flip}
+ .. z4{(dir angle_tip) transformed flip}
+ .. z4'{(dir (-angle_tip)) transformed flip}
+ .. {(dir (-angle_wing_top)) transformed flip}z5b
+ .. z5a{(-dir (-angle_wing_bot)) transformed flip}
+ .. z6{((-stemslant) reflectedabout (origin, up)) transformed flip}
+ -- z7
+ -- cycle;
+
+ labels (range 0 thru 7, 4', 3a, 3b, 5a, 5b);
+endgroup;
enddef;
-
-
-fet_beginchar ("open", "open.01");
- set_char_box (staff_space#, 1.6 linethickness# / 2,
- 0.5 staff_space#, 0.5 staff_space#);
- set_arrow_paths (staff_space, 0.5 staff_space,
- 1.0, 1.6 linethickness);
- fill open_path;
- open_path := open_path yscaled -1;
- fill open_path;
-
- penlabels (1, 2, 3);
- penlabels (4, 5, 6);
-fet_endchar;
-
-
-fet_beginchar ("open", "open.0M1");
- set_char_box (1.6 linethickness# / 2, staff_space#,
- 0.5 staff_space#, 0.5 staff_space#);
- set_arrow_paths (staff_space, 0.5 staff_space,
- 1.0, 1.6 linethickness);
- fill open_path;
- open_path := open_path yscaled -1;
- fill open_path;
- currentpicture := currentpicture xscaled -1;
-fet_endchar;
-
-
-fet_beginchar ("open", "open.11");
- set_char_box (.5 staff_space#, .5 staff_space#,
- 1.0 staff_space#, 1.6 linethickness# / 2);
- set_arrow_paths (staff_space, 0.5 staff_space,
- 1.0, 1.6 linethickness);
- fill open_path;
- open_path := open_path yscaled -1;
- fill open_path;
- currentpicture := currentpicture rotated 90;
-fet_endchar;
-
-
-fet_beginchar ("open", "open.1M1");
- set_char_box (.5 staff_space#, .5 staff_space#,
- 1.6 linethickness# / 2, 1.0 staff_space#);
- set_arrow_paths (staff_space, 0.5 staff_space,
- 1.0, 1.6 linethickness);
- fill open_path;
- open_path := open_path yscaled -1;
- fill open_path;
- currentpicture := currentpicture rotated 90;
- currentpicture := currentpicture yscaled -1;
-fet_endchar;
-
-
-fet_beginchar ("close", "close.01");
- set_char_box (staff_space#, 0, 0.5 staff_space#, 0.5 staff_space#);
- set_arrow_paths (staff_space, 0.5 staff_space, 1.5, blot_diameter);
- fill close_path;
- close_path := close_path yscaled -1;
- fill close_path;
-fet_endchar;
-
-
-fet_beginchar ("close", "close.0M1");
- set_char_box (0, staff_space#, 0.5 staff_space#, 0.5 staff_space#);
- set_arrow_paths (staff_space, 0.5 staff_space, 1.5, blot_diameter);
- fill close_path;
- close_path := close_path yscaled -1;
- fill close_path;
- currentpicture := currentpicture xscaled -1;
-fet_endchar;
-
-
-fet_beginchar ("close", "close.11");
- set_char_box (.5 staff_space#, .5 staff_space#,
- 1.0 staff_space#, 0.0 staff_space#);
- set_arrow_paths (staff_space, 0.5 staff_space, 1.5, blot_diameter);
- fill close_path;
- close_path := close_path yscaled -1;
- fill close_path;
- currentpicture := currentpicture rotated 90;
-fet_endchar;
-
-
-fet_beginchar ("close", "close.1M1");
- set_char_box (.5 staff_space#, .5 staff_space#,
- 0.0 staff_space#, 1.0 staff_space#);
- set_arrow_paths (staff_space, 0.5 staff_space, 1.5, blot_diameter);
- fill close_path;
- close_path := close_path yscaled -1;
- fill close_path;
- currentpicture := currentpicture rotated -90;
-fet_endchar;
-
-
-fet_endgroup ("arrowheads");