%
% Copyright (c) 2011, 2012, Sebastian Schubert <schubert.seb@googlemail.com>
%
% This Font Software is licensed under the SIL Open Font License,
% Version 1.1. This license is in the accompanying file OFL.txt, and
% is also available with a FAQ at: http://scripts.sil.org/OFL
%

def ifneg(expr a,b) =
  if negated: a else: b fi
enddef;

for alpha = 0, 90, 180, 270, 45, 135, 225, 315:
  beginarrow(alpha, 1, ifneg(3/2, 1) * arrow_spread#); "single arrow (" & decimal alpha & ")";
    draw_line(foot_ex, head, false);
    draw_arrowhead(head, alpha, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head - 1/2arrow_spread * dir alpha], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 180, 270, 45, 135, 225, 315:
  beginarrow(alpha, 6/5, ifneg(19/10, 13/10) * arrow_spread#); "double arrow (" & decimal alpha & ")";
    z1 - z0 = z3 - z2 = equal_spread * dir (alpha + 90);
    1/2[z0,z1] = foot_ex;
    1/2[z2,z3] = head;

    draw_line(z0, arrowhead_intersection(head, alpha, 13/10arrow_spread, z0 -- z2), false);
    draw_line(z1, arrowhead_intersection(head, alpha, 13/10arrow_spread, z1 -- z3), false);
    draw_arrowhead(head, alpha, 13/10arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head - arrow_spread * dir alpha], alpha, 19/10arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 45, 135:
  beginarrow(alpha, 6/5, ifneg(3/2, 1) * arrow_spread#); "bidirectional arrow (" & decimal alpha & ")";
    draw_line(foot, head, false);
    draw_arrowhead(head, alpha, arrow_spread, line_thickness);
    draw_arrowhead(foot, alpha+180, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 45, 135:
  beginarrow(alpha, 7/5, ifneg(19/10, 13/10) * arrow_spread#); "double bidirectional arrow (" & decimal alpha & ")";
    z1 - z0 = z3 - z2 = equal_spread * dir (alpha + 90);
    1/2[z0,z1] = foot;
    1/2[z2,z3] = head;

    draw_line(arrowhead_intersection(foot, alpha+180, 13/10arrow_spread, z0 -- z2), arrowhead_intersection(head, alpha, 13/10arrow_spread, z0 -- z2), false);
    draw_line(arrowhead_intersection(foot, alpha+180, 13/10arrow_spread, z1 -- z3), arrowhead_intersection(head, alpha, 13/10arrow_spread, z1 -- z3), false);
    draw_arrowhead(head, alpha, 13/10arrow_spread, line_thickness);
    draw_arrowhead(foot, alpha+180, 13/10arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head], alpha, 19/10arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 180, 270, 45, 135, 225, 315:
  beginarrow(alpha, 5/4, ifneg(3/2, 1) * arrow_spread#); "double-head arrow (" & decimal alpha & ")";
    draw_line(foot_ex, head, false);
    draw_arrowhead(head, alpha, arrow_spread, line_thickness);
    draw_arrowhead(head - 1/4arrow_len * dir alpha, alpha, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head - (1/2arrow_spread + 1/4arrow_len) * dir alpha], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 180, 270, 45, 135, 225, 315:
  beginarrow(alpha, 1, ifneg(3/2, 1) * arrow_spread#); "tailed arrow (" & decimal alpha & ")";
    z0 = foot + 1/2arrow_spread * dir alpha;

    draw_line(z0, head, false);
    draw_arrowhead(head, alpha, arrow_spread, line_thickness);
    draw_arrowhead(z0,   alpha, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 180, 270:
  beginarrow(alpha, 1, ifneg(3/2, 1) * arrow_spread#); "arrow with foot (" & decimal alpha & ")";
    draw_line(foot, head, false);
    draw_line(foot - 1/2arrow_spread * dir (alpha + 90), foot + 1/2arrow_spread * dir (alpha + 90), true);
    draw_arrowhead(head, alpha, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head - 1/2arrow_spread * dir alpha], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 180, 270:
  beginarrow(alpha, 6/5, ifneg(19/10, 13/10) * arrow_spread#); "double arrow with foot (" & decimal alpha & ")";
    z1 - z0 = z3 - z2 = equal_spread * dir (alpha + 90);
    1/2[z0,z1] = foot_ex;
    1/2[z2,z3] = head;

    draw_line(z0, arrowhead_intersection(head, alpha, 13/10arrow_spread, z0 -- z2), false);
    draw_line(z1, arrowhead_intersection(head, alpha, 13/10arrow_spread, z1 -- z3), false);
    draw_line(foot - 13/20arrow_spread * dir (alpha + 90), foot + 13/20arrow_spread * dir (alpha + 90), true);
    draw_arrowhead(head, alpha, 13/10arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head - 1/2arrow_spread * dir alpha], alpha, 19/10arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 180, 270, 45, 135, 225, 315:
  beginarrow(alpha, 1, ifneg(3/2, 1) * arrow_spread#); "left embedding (" & decimal alpha & ")";
    thick := line_thickness;

    z0 = foot + 1/4arrow_spread * dir(alpha + 90);
    1/2[z1,z2] = z0 + 1/4arrow_spread * dir alpha;
    z2 = z1 + 1/2arrow_spread * dir (alpha + 90);
    z3 = head;
    z4 = z2 + 1/2thick * dir alpha;

    penpos0(thick, alpha);
    penpos1(thick, alpha + 90);
    penpos2(thick, alpha - 90);
    penpos3(thick, alpha + 90);
    penpos4(thick, alpha - 90);

    draw_arrowhead(head, alpha, arrow_spread, thick);
    fill stroke z4.e -- z2.e{dir (alpha + 180)} ..
      z0.e{dir (alpha - 90)} .. z1.e{dir alpha} -- z3.e;

    if negated:
      stroke_through_arrow(1/2[foot, head - 1/2arrow_spread * dir alpha], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 180, 270, 45, 135, 225, 315:
  beginarrow(alpha, 1, ifneg(3/2, 1) * arrow_spread#); "right embedding (" & decimal alpha & ")";
    thick := line_thickness;

    z0 = foot - 1/4arrow_spread * dir(alpha + 90);
    1/2[z1,z2] = z0 + 1/4arrow_spread * dir alpha;
    z2 = z1 - 1/2arrow_spread * dir (alpha + 90);
    z3 = head;
    z4 = z2 + 1/2thick * dir alpha;

    penpos0(thick, alpha + 180);
    penpos1(thick, alpha + 90);
    penpos2(thick, alpha - 90);
    penpos3(thick, alpha + 90);
    penpos4(thick, alpha - 90);

    draw_arrowhead(head, alpha, arrow_spread, thick);
    fill stroke z4.e -- z2.e{dir (alpha + 180)} ..
      z0.e{dir (alpha + 90)} .. z1.e{dir alpha} -- z3.e;
    
    if negated:
      stroke_through_arrow(1/2[foot, head - 1/2arrow_spread * dir alpha], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 180, 270, 45, 135, 225, 315:
  beginarrow(alpha, 1, ifneg(3/2, 1) * arrow_spread#); "left harpoon (" & decimal alpha & ")";
    draw_line(foot_ex, head, false);
    draw_arrowhead_left(head, alpha, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head - 1/2arrow_spread * dir alpha], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 180, 270, 45, 135, 225, 315:
  beginarrow(alpha, 1, ifneg(3/2, 1) * arrow_spread#); "right harpoon (" & decimal alpha & ")";
    draw_line(foot_ex, head, false);
    draw_arrowhead_right(head, alpha, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head - 1/2arrow_spread * dir alpha], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 45, 135:
  beginarrow(alpha, 1, ifneg(3/2, 1) * arrow_spread#); "left left harpoon (" & decimal alpha & ")";
    draw_line(foot, head, false);
    draw_arrowhead_left(head, alpha, arrow_spread, line_thickness);
    draw_arrowhead_left(foot, alpha+180, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head], alpha, 3/2arrow_spread)(80, 80, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 45, 135:
  beginarrow(alpha, 1, ifneg(3/2, 1) * arrow_spread#); "right right harpoon (" & decimal alpha & ")";
    draw_line(foot, head, false);
    draw_arrowhead_right(head, alpha, arrow_spread, line_thickness);
    draw_arrowhead_right(foot, alpha+180, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head], alpha, 3/2arrow_spread)(70, 70, 100, 100);
    fi
  endchar;
endfor;

for alpha = 0, 90, 45, 135:
  beginarrow(alpha, 1, ifneg(3/2, 1) * arrow_spread# + equal_spread#); "double left left harpoon (" & decimal alpha & ")";
    z1 - z0 = z1' - z0' = z3 - z2 = z3' - z2' = equal_spread * dir (alpha + 90);
    1/2[z0,z1] = foot;
    1/2[z0',z1'] = foot_ex;
    1/2[z2,z3] = head;
    1/2[z2',z3'] = head_ex;

    draw_line(z2', z0, false);
    draw_line(z1', z3, false);
    draw_arrowhead_left(z3, alpha, arrow_spread, line_thickness);
    draw_arrowhead_left(z0, alpha+180, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head], alpha, 3/2arrow_spread + equal_spread)(80, 80, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 45, 135:
  beginarrow(alpha, 1, ifneg(3/2, 1) * arrow_spread# + equal_spread#); "double right right harpoon (" & decimal alpha & ")";
    z1 - z0 = z1' - z0' = z3 - z2 = z3' - z2' = equal_spread * dir (alpha + 90);
    1/2[z0,z1] = foot;
    1/2[z0',z1'] = foot_ex;
    1/2[z2,z3] = head;
    1/2[z2',z3'] = head_ex;

    draw_line(z0', z2, false);
    draw_line(z3', z1, false);
    draw_arrowhead_right(z2, alpha, arrow_spread, line_thickness);
    draw_arrowhead_right(z1, alpha+180, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head], alpha, 3/2arrow_spread + equal_spread)(70, 70, 100, 100);
    fi
  endchar;
endfor;

for alpha = 0, 90, 180, 270, 45, 135, 225, 315:
  beginarrow(alpha, 1, ifneg(3/2, 1) * arrow_spread#); "broken arrow (" & decimal alpha & ")";
    z0 = ifneg( 4/20, 6/20)[foot,head];
    z1 = ifneg(13/20,11/20)[foot,head];

    draw_line(foot_ex, z0, false);
    draw_line(z1, head, false);
    draw_arrowhead(head, alpha, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[z0, z1], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 180, 270:
  beginarrow(alpha, 1, ifneg(3/2, 1) * arrow_spread#); "multi map (" & decimal alpha & ")";
    draw_line(foot_ex, head - (4/5arrow_spread + 1/4line_thickness) * dir alpha, false);
    draw_circle(head - 2/5arrow_spread * dir alpha, 2/5arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head - 4/5arrow_spread * dir alpha], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 180, 270:
  beginarrow(alpha, 1, ifneg(3/2, 1) * arrow_spread#); "filled multi map (" & decimal alpha & ")";
    draw_line(foot_ex, head_ex - 2/5arrow_spread * dir alpha, false);
    filldraw_circle(head - 2/5arrow_spread * dir alpha, 2/5arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head - 4/5arrow_spread * dir alpha], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

beginarrow(0, 7/5, ifneg(3/2, 1) * arrow_spread#); "double multi map";
  draw_line(foot + (4/5arrow_spread + 1/4line_thickness) * right, head - (4/5arrow_spread + 1/4line_thickness) * right, false);
  draw_circle(head - 2/5arrow_spread * right, 2/5arrow_spread, line_thickness);
  draw_circle(foot + 2/5arrow_spread * right, 2/5arrow_spread, line_thickness);

  if negated:
    stroke_through_arrow(1/2[foot, head], 0, 3/2arrow_spread)(70);
  fi
endchar;

beginarrow(0, 7/5, ifneg(3/2, 1) * arrow_spread#); "filled double multi map";
  draw_line(foot_ex + 2/5arrow_spread * right, head - 2/5arrow_spread * right, false);
  filldraw_circle(head - 2/5arrow_spread * right, 2/5arrow_spread, line_thickness);
  filldraw_circle(foot + 2/5arrow_spread * right, 2/5arrow_spread, line_thickness);

  if negated:
    stroke_through_arrow(1/2[foot, head], 0, 3/2arrow_spread)(70);
  fi
endchar;

for alpha = 0, 180:
  beginarrow(alpha, 7/5, ifneg(3/2, 1) * arrow_spread#); "image of (" & decimal alpha & ")";
    draw_line(foot_ex + 2/5arrow_spread * dir alpha, head - (4/5arrow_spread + 1/4line_thickness) * dir alpha, false);
    filldraw_circle(foot + 2/5arrow_spread * dir alpha, 2/5arrow_spread, line_thickness);
    draw_circle(head - 2/5arrow_spread * dir alpha, 2/5arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 180, 270:
  beginarrow(alpha, 1, 3/4plus_size# + ifneg(1,0) * arrow_spread#); "pitchfork (" & decimal alpha & ")";
    draw_line(foot_ex, head_ex, false);
    draw_subset(a, foot + 1/2arrow_len * dir alpha, foot_ex, 3/4plus_size, line_thickness);

    if negated:
      stroke_through_arrow(1/4[foot, head], alpha, 3/4plus_size + arrow_spread)(80, 80, 100, 100, 80, 80, 100, 100);
    fi
  endchar;
endfor;

for alpha = 0, 90, 180, 270, 45, 135, 225, 315:
  beginarrow(alpha, 1, 2arrow_spread#+line_thickness#); "parallel arrows (" & decimal alpha & ")";
    z1 - z0 = z3 - z2 = (arrow_spread+line_thickness) * dir (alpha + 90);
    1/2[z0,z1] = foot_ex;
    1/2[z2,z3] = head;

    draw_line(z0, z2, false);
    draw_line(z1, z3, false);
    draw_arrowhead(z2, alpha, arrow_spread, line_thickness);
    draw_arrowhead(z3, alpha, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head - 1/2arrow_spread * dir alpha], alpha, 2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 45, 135:
  beginarrow(alpha, 1, 2arrow_spread#); "anti-parallel arrows right left (" & decimal alpha & ")";
    z1 - z0 = z1' - z0' = z3 - z2 = z3' - z2' = arrow_spread * dir (alpha + 90);
    1/2[z0,z1] = foot;
    1/2[z0',z1'] = foot_ex;
    1/2[z2,z3] = head;
    1/2[z2',z3'] = head_ex;

    draw_line(z2', z0, false);
    draw_line(z1', z3, false);
    draw_arrowhead(z3, alpha, arrow_spread, line_thickness);
    draw_arrowhead(z0, alpha+180, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head], alpha, 2arrow_spread)(80, 80, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 45, 135:
  beginarrow(alpha, 1, 2arrow_spread#); "anti-parallel arrows left right (" & decimal alpha & ")";
    z1 - z0 = z1' - z0' = z3 - z2 = z3' - z2' = arrow_spread * dir (alpha + 90);
    1/2[z0,z1] = foot;
    1/2[z0',z1'] = foot_ex;
    1/2[z2,z3] = head;
    1/2[z2',z3'] = head_ex;

    draw_line(z0', z2, false);
    draw_line(z3', z1, false);
    draw_arrowhead(z2, alpha, arrow_spread, line_thickness);
    draw_arrowhead(z1, alpha+180, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head], alpha, 2arrow_spread)(70, 70, 100, 100);
    fi
  endchar;
endfor;

for sign = 1, -1:
for alpha = 0, 90, 180, 270:
  beginarrow(alpha, 1, ifneg(3/2, 1) * arrow_spread#);
  if sign > 0: "left right" else: "right left" fi & " wave arrow (" & decimal alpha & ")";
    thick := line_thickness;

    z0 = foot - sign * 1/8arrow_spread * dir (alpha + 90);
    z1 = 4/18[foot,head] + sign * 1/4arrow_spread * dir (alpha + 90);
    z2 = 7/18[foot,head];
    z3 = 10/18[foot,head] - sign * 1/4arrow_spread * dir (alpha + 90);
    z4 = 12/18[foot,head] - sign * 1/8arrow_spread * dir (alpha + 90);
    z5 = 14/18[foot,head];
    z6 = head;

    penpos0(thick, alpha - 90 + sign * 55);
    penpos1(thick, alpha - 90);
    penpos2(thick, alpha - 90 - sign * 55);
    penpos3(thick, alpha - 90);
    penpos4(thick, alpha - 90 + sign * 35);
    penpos5(thick, alpha - 90);
    penpos6(thick, alpha - 90);

    penlabels(0,1,2,3,4,5,6);

    fill stroke z0.e{dir (alpha + sign * 55)} .. z1.e{dir alpha} .. z2.e{dir (alpha - sign * 55)} .. z3.e{dir alpha} .. z4.e{dir (alpha + sign * 35)} ... {dir alpha}z5.e -- z6.e;
    draw_arrowhead(z6, alpha, arrow_spread, thick);

    if negated:
      stroke_through_arrow(1/2[foot, head - 1/2arrow_spread * dir alpha], alpha, 3/2arrow_spread)(70, 70, 70, 70, 70, 70, 70, 70);
    fi
  endchar;
endfor;
endfor;

for sign = 1, -1:
  for alpha = 0, 90:
    beginarrow(alpha, 6/5, ifneg(3/2, 1) * arrow_spread#);
    if sign > 0: "left right" else: "right left" fi & " bidirectional wave arrow (" & decimal alpha & ")";
      thick := line_thickness;

      z0 = foot;
      z1 = 4/22[foot,head];
      z2 = 6/22[foot,head] + sign * 1/8arrow_spread * dir (alpha + 90);
      z3 = 8/22[foot,head] + sign * 1/4arrow_spread * dir (alpha + 90);
      z4 = 11/22[foot,head];
      z5 = 14/22[foot,head] - sign * 1/4arrow_spread * dir (alpha + 90);
      z6 = 16/22[foot,head] - sign * 1/8arrow_spread * dir (alpha + 90);
      z7 = 18/22[foot,head];
      z8 = head;

      penpos0(thick, alpha - 90);
      penpos1(thick, alpha - 90);
      penpos2(thick, alpha - 90 + sign * 35);
      penpos3(thick, alpha - 90);
      penpos4(thick, alpha - 90 - sign * 55);
      penpos5(thick, alpha - 90);
      penpos6(thick, alpha - 90 + sign * 35);
      penpos7(thick, alpha - 90);
      penpos8(thick, alpha - 90);

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

      fill stroke z0e. -- z1.e{dir alpha} .. z2.e{dir (alpha + sign * 35)} .. z3.e{dir alpha} .. z4.e{dir (alpha - sign * 55)} .. z5.e{dir alpha} ... z6.e{dir (alpha + sign * 35)} .. {dir alpha}z7.e -- z8.e;
      draw_arrowhead(z0, alpha + 180, arrow_spread, thick);
      draw_arrowhead(z8, alpha, arrow_spread, thick);

      if negated:
        stroke_through_arrow(1/2[foot, head], alpha, 3/2arrow_spread)(70, 70, 70, 70);
      fi
    endchar;
  endfor;
endfor;

for alpha = 0, 90, 180, 270, 45, 135, 225, 315:
  beginarrow(alpha, 1, ifneg(3/2,1) * arrow_spread#); "right bend arrow (" & decimal alpha & ")";
    thick := line_thickness;

    z0 = foot - 1/4arrow_spread * dir (alpha + 90);
    z1 = 9/20[foot,head] + 1/4arrow_spread * dir (alpha + 90);
    z2 = 19/20[foot,head] - 1/2arrow_spread * dir (alpha + 90);

    penpos0(thick, alpha - 35);
    penpos1(thick, alpha - 90);
    penpos2(thick, alpha - 150);

    fill stroke z0.e{dir (alpha + 55)} .. z1.e .. {dir (alpha - 60)}z2.e;
    draw_arrowhead(z2, alpha - 50, arrow_spread, thick);

    if negated:
      stroke_through_arrow(1/10[z1,z2] + 1/8arrow_spread * dir (alpha - 90), alpha, 3/2arrow_spread)(80, 80, 80, 80, 80, 80, 80, 80);
    fi
  endchar;
endfor;

for alpha = 0, 90, 180, 270, 45, 135, 225, 315:
  beginarrow(alpha, 1, ifneg(3/2,1) * arrow_spread#); "left bend arrow (" & decimal alpha & ")";
    thick := line_thickness;

    z0 = foot + 1/4arrow_spread * dir (alpha + 90);
    z1 = 9/20[foot,head] - 1/4arrow_spread * dir (alpha + 90);
    z2 = 19/20[foot,head] + 1/2arrow_spread * dir (alpha + 90);

    penpos0(thick, alpha + 35);
    penpos1(thick, alpha + 90);
    penpos2(thick, alpha + 150);

    fill stroke z0.e{dir (alpha - 55)} .. z1.e .. {dir (alpha + 60)}z2.e;
    draw_arrowhead(z2, alpha + 50, arrow_spread, thick);

    if negated:
      stroke_through_arrow(1/10[z1,z2] + 1/8arrow_spread * dir (alpha + 90), alpha, 3/2arrow_spread)(110, 110, 110, 110, 110, 110, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 90, 180, 270, 45, 135, 225, 315:
  beginarrow(alpha, 6/5, ifneg(3/2,1) * arrow_spread#); "bidirectional bend arrow (" & decimal alpha & ")";
    thick := line_thickness;

    z0 = 1/20[foot,head] - 1/2arrow_spread * dir (alpha + 90);
    z1 = 1/2[foot,head] + 1/4arrow_spread * dir (alpha + 90);
    z2 = 19/20[foot,head] - 1/2arrow_spread * dir (alpha + 90);

    penpos0(thick, alpha - 30);
    penpos1(thick, alpha - 90);
    penpos2(thick, alpha - 150);

    fill stroke z0.e{dir (alpha + 60)} .. z1.e .. {dir (alpha - 60)}z2.e;
    draw_arrowhead(z0, alpha + 230, arrow_spread, thick);
    draw_arrowhead(z2, alpha - 50, arrow_spread, thick);

    if negated:
      stroke_through_arrow(z1 + 1/8arrow_spread * dir (alpha - 90), alpha, 3/2arrow_spread)(80, 80, 100, 100, 80, 80, 100, 100);
    fi
  endchar;
endfor;

for alpha = 0, 180:
  beginarrow(alpha, 1, ifneg(3/2,1) * arrow_spread#); "headless arrow with foot (" & decimal alpha & ")";
    draw_line(foot_ex, head_ex, false);
    draw_line(foot - 1/2arrow_spread * dir (alpha + 90), foot + 1/2arrow_spread * dir (alpha + 90), true);

    if negated:
      stroke_through_arrow(1/2[foot, head], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for sign = 1, -1:
  for alpha = 0, 90, 180, 270:
    beginoperator(large_op_size#, 1);
      if sign > 0: "right" else: "left" fi & " circle arrow (" & decimal alpha & ")";

      thick := line_thickness;
      r := (w - 2side_bearing)/2 - arrow_spread/3;

      for i = 0 upto 7:
        z[i] = centre + r * dir (alpha + i/8 * 360);
        penpos[i](thick, alpha + i/8 * 360);
      endfor;

      z0' = centre + r * dir (alpha + 10);
      penpos0'(thick, alpha + 10);
      z0'' = centre + r * dir (alpha - 10);
      penpos0''(thick, alpha - 10);

      penlabels(0',0'',1,2,3,4,5,6,7);

      fill stroke z0'.e{dir (alpha + 100)} .. z1.e .. z2.e .. z3.e .. z4.e .. z5.e .. z6.e .. z7.e .. {dir (alpha + 80)}z0''.e;

      if sign > 0:
        draw_arrowhead(z0'', (alpha + 65), arrow_spread, thick);
      else:
        draw_arrowhead(z0', (alpha - 65), arrow_spread, thick);
      fi;

      if negated:
         1/2[z8,z9] = centre;
         if (alpha = 90) or (alpha = 270):
           y8 - y9 = large_op_size * sind 45;
           z8 - z9 = whatever * dir 40;
         else:
           y8 - y9 = large_op_size;
           z8 - z9 = whatever * dir 80;
         fi

         draw_straight(z8, z9, stroke_through_thickness, false);
      fi
    endchar;
  endfor;
endfor;

for alpha = 0, 90, 180, 270:
  beginarrow(alpha, 6/5, ifneg(21/10, 14/10) * arrow_spread#+line_thickness#/2); "triple arrow (" & decimal alpha & ")";
    z1 - z0 = z2 - z1 = 2/3equal_spread * dir (alpha + 90);
    z1 = foot_ex;
    z4 - z3 = z5 - z4 = 2/3equal_spread * dir (alpha + 90);
    z4 = head_ex;

    draw_straight(z0, arrowhead_intersection(head, alpha, 3/2arrow_spread, z0 -- z3), 4/5line_thickness, false);
    draw_straight(z1, arrowhead_intersection(head, alpha, 3/2arrow_spread, z1 -- z4), 4/5line_thickness, false);
    draw_straight(z2, arrowhead_intersection(head, alpha, 3/2arrow_spread, z2 -- z5), 4/5line_thickness, false);
    draw_arrowhead(head, alpha, 3/2arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head - arrow_spread * dir alpha], alpha, 21/10arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 180:
  beginarrow(alpha, 2, ifneg(3/2, 1) * arrow_spread#); "long single arrow (" & decimal alpha & ")";
    draw_line(foot_ex, head, false);
    draw_arrowhead(head, alpha, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head - 1/2arrow_spread * dir alpha], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 180:
  beginarrow(alpha, 2, ifneg(19/10, 13/10) * arrow_spread#); "long double arrow (" & decimal alpha & ")";
    z1 - z0 = z3 - z2 = equal_spread * dir (alpha + 90);
    1/2[z0,z1] = foot_ex;
    1/2[z2,z3] = head;

    draw_line(z0, arrowhead_intersection(head, alpha, 13/10arrow_spread, z0 -- z2), false);
    draw_line(z1, arrowhead_intersection(head, alpha, 13/10arrow_spread, z1 -- z3), false);
    draw_arrowhead(head, alpha, 13/10arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head - arrow_spread * dir alpha], alpha, 19/10arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0:
  beginarrow(alpha, 2, ifneg(3/2, 1) * arrow_spread#); "long bidirectional arrow (" & decimal alpha & ")";
    draw_line(foot, head, false);
    draw_arrowhead(head, alpha, arrow_spread, line_thickness);
    draw_arrowhead(foot, alpha+180, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0:
  beginarrow(alpha, 2, ifneg(19/10, 13/10) * arrow_spread#); "long double bidirectional arrow (" & decimal alpha & ")";
    z1 - z0 = z3 - z2 = equal_spread * dir (alpha + 90);
    1/2[z0,z1] = foot;
    1/2[z2,z3] = head;

    draw_line(arrowhead_intersection(foot, alpha+180, 13/10arrow_spread, z0 -- z2), arrowhead_intersection(head, alpha, 13/10arrow_spread, z0 -- z2), false);
    draw_line(arrowhead_intersection(foot, alpha+180, 13/10arrow_spread, z1 -- z3), arrowhead_intersection(head, alpha, 13/10arrow_spread, z1 -- z3), false);
    draw_arrowhead(head, alpha, 13/10arrow_spread, line_thickness);
    draw_arrowhead(foot, alpha+180, 13/10arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head], alpha, 19/10arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 180:
  beginarrow(alpha, 2, ifneg(3/2, 1) * arrow_spread#); "long arrow with foot (" & decimal alpha & ")";
    draw_line(foot, head, false);
    draw_line(foot - 1/2arrow_spread * dir (alpha + 90), foot + 1/2arrow_spread * dir (alpha + 90), true);
    draw_arrowhead(head, alpha, arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head - 1/2arrow_spread * dir alpha], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 180:
  beginarrow(alpha, 2, ifneg(19/10, 13/10) * arrow_spread#); "long double arrow with foot (" & decimal alpha & ")";
    z1 - z0 = z3 - z2 = equal_spread * dir (alpha + 90);
    1/2[z0,z1] = foot_ex;
    1/2[z2,z3] = head;

    draw_line(z0, arrowhead_intersection(head, alpha, 13/10arrow_spread, z0 -- z2), false);
    draw_line(z1, arrowhead_intersection(head, alpha, 13/10arrow_spread, z1 -- z3), false);
    draw_line(foot - 13/20arrow_spread * dir (alpha + 90), foot + 13/20arrow_spread * dir (alpha + 90), true);
    draw_arrowhead(head, alpha, 13/10arrow_spread, line_thickness);

    if negated:
      stroke_through_arrow(1/2[foot, head - arrow_spread * dir alpha], alpha, 19/10arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

for alpha = 0, 180:
  beginarrow(alpha, 2, ifneg(3/2, 1) * arrow_spread#); "long wave arrow (" & decimal alpha & ")";
    thick := line_thickness;
    sign := if alpha > 0: 1 else: -1 fi;

    z0 = foot - 1/8arrow_spread * up;
    z1 = 4/43[foot,head] + 1/4arrow_spread * up;
    z2 = 7/43[foot,head];
    z3 = 10/43[foot,head] - 1/4arrow_spread * up;
    z4 = 13/43[foot,head];
    z5 = 16/43[foot,head] + 1/4arrow_spread * up;
    z6 = 19/43[foot,head];
    z7 = 22/43[foot,head] - 1/4arrow_spread * up;
    z8 = 25/43[foot,head];
    z9 = 28/43[foot,head] + 1/4arrow_spread * up;
    z10 = 31/43[foot,head];
    z11 = 34/43[foot,head] - 1/4arrow_spread * up;
    z12 = 36/43[foot,head] - 1/8arrow_spread * up;
    z13 = 38/43[foot,head];
    z14 = head;

    penpos0(thick, sign * 35);
    penpos1(thick, sign * 90);
    penpos2(thick, sign * 145);
    penpos3(thick, sign * 90);
    penpos4(thick, sign * 35);
    penpos5(thick, sign * 90);
    penpos6(thick, sign * 145);
    penpos7(thick, sign * 90);
    penpos8(thick, sign * 35);
    penpos9(thick, sign * 90);
    penpos10(thick, sign * 145);
    penpos11(thick, sign * 90);
    penpos12(thick, sign * 45);
    penpos13(thick, sign * 90);
    penpos14(thick, sign * 90);

    penlabels(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14);

    fill stroke z0e{dir (sign * 35 + 90)} .. z1.e{dir (sign * 90 + 90)} .. z2.e{dir (sign * 145 + 90)} .. z3.e{dir (sign * 90 + 90)} .. z4.e{dir (sign * 35 + 90)} .. z5.e{dir (sign * 90 + 90)} .. z6.e{dir (sign * 145 + 90)} .. z7.e{dir (sign * 90 + 90)} .. z8.e{dir (sign * 35 + 90)} .. z9.e{dir (sign * 90 + 90)} .. z10.e{dir (sign * 145 + 90)} .. z11.e{dir (sign * 90 + 90)} .. z12.e{dir (sign * 45 + 90)} .. {dir (sign * 90 + 90)}z13.e -- z14.e;
    draw_arrowhead(z14, alpha, arrow_spread, thick);

    if negated:
      stroke_through_arrow(1/2[foot, head - 1/2arrow_spread * dir alpha], alpha, 3/2arrow_spread)(70, 70, 70, 70, 70, 70, 70, 70);
    fi
  endchar;
endfor;

for alpha = 0, 180:
  beginarrow(alpha, 2, ifneg(3/2,1) * arrow_spread#); "long headless arrow with foot (" & decimal alpha & ")";
    draw_line(foot_ex, head_ex, false);
    draw_line(foot - 1/2arrow_spread * dir (alpha + 90), foot + 1/2arrow_spread * dir (alpha + 90), true);

    if negated:
      stroke_through_arrow(1/2[foot, head], alpha, 3/2arrow_spread)(70, 70, 110, 110, 70, 70, 110, 110);
    fi
  endchar;
endfor;

if not negated:
  for sign = 1, -1:
    beginsymbol(4/3arrow_spread# + line_thickness# + 2side_bearing#, vcentre(2arrow_spread# + line_thickness#)); "left shift";
      y0 = y1 = h - 1/2arrow_spread - 1/2line_thickness;
      y2 = -d + 1/2line_thickness;
      1/2[x0,x1] = w/2;
      x1 - x0 = sign * 4/3arrow_spread;
      x2 = x1;

      draw_line(z2, z1, true);
      draw_line(z1, z0, false);
      draw_arrowhead(z0, 90 + sign * 90, arrow_spread, line_thickness);
    endchar;
  endfor;

  for sign = 1, -1:
    beginsymbol(4/3arrow_spread# + line_thickness# + 2side_bearing#, vcentre(2arrow_spread# + line_thickness#)); "left down shift";
      y0 = y1 = -d + 1/2arrow_spread + 1/2line_thickness;
      y2 = h - 1/2line_thickness;
      1/2[x0,x1] = w/2;
      x1 - x0 = sign * 4/3arrow_spread;
      x2 = x1;

      draw_line(z2, z1, true);
      draw_line(z1, z0, false);
      draw_arrowhead(z0, 90 + sign * 90, arrow_spread, line_thickness);
    endchar;
  endfor;

  for sign = -1, 1:
    beginsymbol(arrow_diag_len# + 2side_bearing#, vcentre(arrow_diag_len#)); "loop arrow";
      thick := line_thickness;
      arrow_len := arrow_diag_len;
      pair centre;
      centre := (w/2, (h-d)/2);

      z0 = centre + sign * (arrow_len - line_thickness)/2 * left;
      z1 = centre + arrow_len/2 * down;
      z2 = centre + (arrow_len - line_thickness)/4 * up;
      z3 = centre + sign * (arrow_len - line_thickness)/4 * right;
      z4 = centre + (arrow_len - line_thickness) * (1/4sign, 1/2);
      z5 = centre + (arrow_len - line_thickness) * (1/2sign, 1/4);

      penpos0(thick, - sign * 90);
      penpos1(thick, 180);
      penpos2(thick, 180);
      penpos3(thick, - sign * 90);
      penpos4(thick, sign * 90);
      penpos5(thick, 0);

      fill stroke z0e -- z3e{sign * right} .. {up}z5e .. {sign * left}z4e .. {down}z2e -- z1e;
      draw_arrowhead(z0, 90 + sign * 90, arrow_spread, thick);

      penlabels(0,1,2,3,4,5);
    endchar;
  endfor;
fi
