% Feta (not the Font-En-Tja) music font --  ancient clefs
% This file is part of LilyPond, the GNU music typesetter.
%
% Copyright (C) 2001--2022 Juergen Reuter <reuter@ipd.uka.de>
%
% 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 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 ("clefs");

%
% character aligment:
%
%   Each clef is associated with a particular pitch: the treble clef
%   with the `g', the alto clef with the `c', the bass clef with the
%   `f', etc.  The shape of each clef character defines a vertical
%   position that is assumed to represent this pitch.  For the treble
%   clef, it is the vertical position of the center of the spiral
%   ending that represents the `g' pitch.  For the bass clef, it is
%   the center between the two fat dots that define the vertical
%   position of the `f' pitch.  For the alto clef, it is the vertical
%   center of the clef that is aligned with the `c' pitch.  For each
%   clef character, this center should be vertically aligned with the
%   point (0, 0).  The horizontal alignment of each clef character
%   should be such that the vertical line through the point (0, 0)
%   touches the left-most edge of the clef.
%
%   TODO: document exact_center
%
% set_char_box() conventions:
%
% * breapth: Ignored (as far as I know).  Should be set to 0.
%
% * width: Should match the clef's width.
%
% * depth: Should match the bottom edge of the clef.  Affects vertical
%   collision handling.
%
% * height: Should match the top edge of the clef.  Affects vertical
%   collision handling.
%


%%%%%%%%
%
%
%
% Editio Vaticana
%
%
%
def draw_vaticana_do_clef (expr exact_center, reduction) =
  save reduced_il;

  reduced_il# = staff_space# * reduction;

  set_char_box (0 - xpart exact_center,
                0.5 reduced_il# + xpart exact_center,
                0.8 reduced_il# - ypart exact_center,
                0.8 reduced_il# + ypart exact_center);

  define_pixels (reduced_il);

  save pat, ellipse, clef, T;
  path pat, ellipse, clef;
  transform T;

  T := identity xscaled 0.6 linethickness
                yscaled 0.6 reduced_il;
  pickup pencircle transformed T;
  ellipse := reverse fullcircle transformed T;

  save xoffs, yoffs;

  xoffs# = xpart exact_center;
  yoffs# = ypart exact_center;

  define_pixels (xoffs, yoffs);

  rt z11 = (xoffs + 0.50 reduced_il, yoffs - .45 reduced_il);
  z12 = (xoffs + 0.25 reduced_il, yoffs - .50 reduced_il);
  lft z13 = (xoffs + 0.00 reduced_il, yoffs - .28 reduced_il);
  lft z14 = (xoffs, yoffs);

  pat := z11
         .. z12
         .. z13
         -- z14;

  save shift;
  pair shift;

  % adjust vertically to fit into bounding box
  shift = find_tangent_shift (((0, -d + 0.3 reduced_il)
                              -- (w, -d + 0.3 reduced_il)), pat,
                              (0, -d / 2), (0, d / 2));
  pat := pat shifted shift;

  clef := rt z14{down}
          .. top (point 1 of pat)
          .. get_subpath (ellipse,
                          -direction 0 of pat, direction 0 of pat,
                          point 0 of pat)
          .. bot (point 1 of pat)
          .. get_subpath (ellipse,
                          direction 2 of pat, up,
                          point 2 of pat);

  fill clef
       -- reverse clef yscaled -1
       -- cycle;

  labels (11, 12, 13, 14);
enddef;


fet_beginchar ("Ed. Vat. Do clef", "vaticana.do");
  draw_staff_if_debugging (-1, 3);
  draw_vaticana_do_clef ((0, 0), 1.0);
fet_endchar;


fet_beginchar ("Ed. Vat. Do clef (reduced)", "vaticana.do_change");
  draw_vaticana_do_clef ((0, 0), 1.0); % no reduction
fet_endchar;


def draw_vaticana_fa_clef (expr exact_center, reduction) =
  save reduced_il, xoffs, yoffs;

  reduced_il# = staff_space# * reduction;
  xoffs# = xpart exact_center;
  yoffs# = ypart exact_center;

  define_pixels (reduced_il, xoffs, yoffs);

  % left-handed punctum
  save ellipse, pat, T;
  path ellipse, pat;
  transform T;

  T := identity xscaled 0.6 linethickness
                yscaled 0.5 reduced_il;
  pickup pencircle transformed T;
  ellipse := reverse fullcircle transformed T;

  lft z21 = (xoffs + 0.00 reduced_il, yoffs + 0.00 reduced_il);
  z22 = (xoffs + 0.25 reduced_il, yoffs + 0.05 reduced_il);
  rt z23 = (xoffs + 0.50 reduced_il, yoffs - 0.05 reduced_il);

  pat := z21
         .. z22
         .. z23;

  fill get_subpath (ellipse,
                    -direction 0 of pat, direction 0 of pat, z21)
       .. top z22
       .. get_subpath (ellipse,
                       direction 2 of pat, -direction 2 of pat, z23)
       .. bot z22
       .. cycle;

  % stem
  pickup pencircle scaled 0.6 linethickness;

  x23 = x24;
  yoffs = bot y24 + 1.5 reduced_il;

  draw_rounded_block (bot lft z24, top rt z23, 0.6 linethickness);

  labels (21, 22, 23, 24);

  % right-handed puncta as in do clef
  draw_vaticana_do_clef (exact_center + (0.55 reduced_il#, 0),
                         reduction);

  set_char_box (0 - xpart exact_center,
                1.05 reduced_il# + xpart exact_center,
                1.5 reduced_il# - ypart exact_center,
                0.8 reduced_il# + ypart exact_center);
enddef;


fet_beginchar ("Ed. Vat. Fa clef", "vaticana.fa");
  draw_staff_if_debugging (-1, 3);
  draw_vaticana_fa_clef ((0, 0), 1.0);
fet_endchar;


fet_beginchar ("Ed. Vat. Fa clef (reduced)", "vaticana.fa_change");
  draw_vaticana_fa_clef ((0, 0), 1.0); % no reduction
fet_endchar;


%%%%%%%%
%
%
%
% Editio Medicaea
%
%
%
def draw_medicaea_do_clef (expr exact_center, reduction) =
  save reduced_il, reduced_slt;

  reduced_il# = staff_space# * reduction;
  reduced_slt# = linethickness# * reduction;

  define_pixels (reduced_il);
  define_pixels (reduced_slt);

  set_char_box (0 - xpart exact_center,
                1.0 reduced_il# + xpart exact_center,
                1.5 reduced_il# - ypart exact_center,
                1.5 reduced_il# + ypart exact_center);

  save flag_height;

  flag_height# = 0.5 reduced_il#;

  define_pixels (flag_height);

  save xoffs, yoffs;

  xoffs# = xpart exact_center;
  yoffs# = ypart exact_center;

  define_pixels (xoffs, yoffs);

  % flags
  save ellipse, T;
  path ellipse;
  transform T;

  T := identity xscaled reduced_slt
                yscaled flag_height;
  pickup pencircle transformed T;
  ellipse := reverse fullcircle transformed T;

  xoffs = lft x1 = rt x2 - reduced_il;
  y1 = yoffs + 0.5 (reduced_il - flag_height - staff_space);
  y2 = y1 - reduced_il + flag_height;

  fill top z1
       -- get_subpath (ellipse, z2 - z1, z1 - z2, z2)
       -- bot z1
       -- cycle;

  xoffs = lft x3 = rt x4 - reduced_il;
  y3 = yoffs + 0.5 (reduced_il - flag_height + staff_space);
  y4 = y3 - reduced_il + flag_height;

  fill top z3
       -- get_subpath (ellipse, z4 - z3, z3 - z4, z4)
       -- bot z3
       -- cycle;

  % stem
  pickup pencircle scaled reduced_slt;

  lft x5 = lft x6 = xoffs;
  yoffs = top y6 - 1.5 reduced_il = bot y5 + 1.5 reduced_il;

  draw_rounded_block (bot lft z5, top rt z6, reduced_slt);

  labels (1, 2, 3, 4, 5, 6);
enddef;


fet_beginchar ("Ed. Med. Do clef", "medicaea.do");
  draw_staff_if_debugging (-1, 3);
  draw_medicaea_do_clef ((0, 0), 1.0);
fet_endchar;


fet_beginchar ("Ed. Med. Do clef (reduced)", "medicaea.do_change");
  draw_medicaea_do_clef ((0, 0), .8);
fet_endchar;


def draw_medicaea_fa_clef (expr exact_center, reduction) =
  % inspired by Regensburger Edition of Medicaea (1885/86), in:
  % MGG, volume 2, col. 1327 ("Choralreform"), fig. 2.

  save reduced_il, reduced_slt;

  reduced_il# = staff_space# * reduction;
  reduced_slt# = linethickness# * reduction;

  define_pixels (reduced_il);
  define_pixels (reduced_slt);

  save xoffs, yoffs;

  xoffs# = xpart exact_center;
  yoffs# = ypart exact_center;

  define_pixels (xoffs, yoffs);

  % stem
  pickup pencircle scaled reduced_slt;

  x11 = x12 = xoffs + 0.4 reduced_il;
  y11 = yoffs = bot y12 + 1.5 reduced_il;

  draw_rounded_block (bot lft z12, top rt z11, reduced_slt);

  % left-handed punctum
  save ellipse, T;
  path ellipse;
  transform T;

  T := identity xscaled reduced_slt
                yscaled reduced_il;
  pickup pencircle transformed T;
  ellipse := reverse fullcircle transformed T;

  lft z13 = (xoffs, yoffs);
  rt z14 = z11 + (reduced_slt / 2, 0);

  fill get_subpath (ellipse, left, right, z13)
       -- get_subpath (ellipse, right, left, z14)
       -- cycle;

  labels (11, 12, 13, 14);

  % right-handed puncta as in do clef
  draw_medicaea_do_clef (exact_center + (0.7 reduced_il#, 0),
                         reduction);

  set_char_box (0 - xpart exact_center,
                1.7 reduced_il# + xpart exact_center,
                1.5 reduced_il# - ypart exact_center,
                1.5 reduced_il# + ypart exact_center);
enddef;


fet_beginchar ("Ed. Med. Fa clef", "medicaea.fa");
  draw_staff_if_debugging (-1, 3);
  draw_medicaea_fa_clef ((0, 0), 1.0);
fet_endchar;


fet_beginchar ("Ed. Med. Fa clef (reduced)", "medicaea.fa_change");
  draw_medicaea_fa_clef ((0, 0), .8);
fet_endchar;


%%%%%%%%
%
%
%
% Mensural Notation
%
%
%

%
% width:        interval from left end to right end
% height:       interval from bottom of lower beam to top of upper beam
% exact_center: the coordinates of the vertical center point of the
%               left edge.
%
def draw_brevis (expr exact_center, bwidth, bheight, blinethickness) =
  save brevis_width, brevis_height, linethickness;

  brevis_width# = bwidth;
  brevis_height# = bheight;
  linethickness# = blinethickness;

  save beam_width, beam_height;
  save serif_size, serif_protrude, hole_height;

  beam_width# = 1.4 linethickness#;
  hole_height# = 3 linethickness#;
  2 beam_height# + hole_height# = brevis_height#;
  serif_size# = (hole_height# - linethickness#) / 2;
  serif_protrude# = 1.5 serif_size#;

  save xoffs, yoffs;

  xoffs# = xpart exact_center;
  yoffs# = ypart exact_center;

  define_pixels (xoffs, yoffs);
  define_pixels (brevis_width, brevis_height, linethickness);
  define_pixels (beam_width, beam_height, serif_size, serif_protrude);

  z1l = (xoffs, yoffs - linethickness);
  z2r = z1r + serif_size * (1, -1);
  z3l = z2l + (-serif_size, -serif_protrude);

  penpos1 (beam_width, 0);
  penpos2 (beam_height, 90);
  penpos3 (beam_width, 180);

  save pat_in, pat_out;
  path pat_in, pat_out;

  pat_out := z3r{down}
             .. z3l{up}
             .. z2l{right};
  pat_out := pat_out
             -- reverse pat_out xscaled -1
                                shifted (2 xoffs + brevis_width, 0);
  pat_out := pat_out
             -- reverse pat_out yscaled -1
                                shifted (0, 2 yoffs)
             -- cycle;

  pat_in := z1r{down}
            .. z2r{right};
  pat_in := pat_in
            -- reverse pat_in xscaled -1
                              shifted (2 xoffs + brevis_width, 0);
  pat_in := pat_in
            -- reverse pat_in yscaled -1
                              shifted (0, 2 yoffs)
            -- cycle;

  fill pat_out;
  unfill pat_in;

  penlabels (1, 2, 3);
enddef;


%
% Draw two brevis notes; the second one shifted down by `shift'.
% The other parameters are the same as with `draw_brevis'.
%
def draw_double_brevis (expr exact_center, bwidth, bheight,
                             blinethickness, shift) =
  save brevis_width, brevis_height, linethickness;

  brevis_width# = bwidth;
  brevis_height# = bheight;
  linethickness# = blinethickness;

  save beam_width, beam_height;
  save serif_size, serif_protrude, hole_height;

  beam_width# = 1.4 linethickness#;
  hole_height# = 3 linethickness#;
  2 beam_height# + hole_height# = brevis_height#;
  serif_size# = (hole_height# - linethickness#) / 2;
  serif_protrude# = 1.5 serif_size#;

  save xoffs, yoffs;

  xoffs# = xpart exact_center;
  yoffs# = ypart exact_center;

  define_pixels (xoffs, yoffs);
  define_pixels (brevis_width, brevis_height, linethickness);
  define_pixels (beam_width, beam_height, serif_size, serif_protrude);

  z1l = (xoffs, yoffs - linethickness);
  z2r = z1r + serif_size * (1, -1);
  z3l = z2l + (-serif_size, -serif_protrude);

  penpos1 (beam_width, 0);
  penpos2 (beam_height, 90);
  penpos3 (beam_width, 180);

  z4 = z1 shifted (0, -shift);
  z5 = z2 shifted (0, -shift);
  z6 = z3 shifted (0, -shift);

  penpos4 (beam_width, 0);
  penpos5 (beam_height, 90);
  penpos6 (beam_width, 180);

  save pat_in, pat_out;
  path pat_in, pat_out;

  pat_out := z6r{down}
             .. z6l{up}
             .. z5l{right};
  pat_out := pat_out
             -- reverse pat_out xscaled -1
                                shifted (2 xoffs + brevis_width, 0);
  pat_out := pat_out
             -- reverse pat_out yscaled -1
                                shifted (0, shift - 2 yoffs)
             -- cycle;

  fill pat_out;

  pat_in := z1r{down}
            .. z2r{right};
  pat_in := pat_in
            -- reverse pat_in xscaled -1
                              shifted (2 xoffs + brevis_width, 0);
  pat_in := pat_in
            -- reverse pat_in yscaled -1
                              shifted (0, 2 yoffs)
            -- cycle;

  unfill pat_in;
  unfill pat_in shifted (0, -shift);

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


def draw_neomensural_c_clef (expr exact_center, reduction) =
  save reduced_il, reduced_slt, stem_width;

  reduced_il# = staff_space# * reduction;
  reduced_slt# = linethickness# * reduction;
  stem_width# = 1.4 reduced_slt#;

  define_pixels (reduced_il, reduced_slt, stem_width);

  set_char_box (0 - xpart exact_center,
                2 reduced_il# + 6 reduced_slt# + xpart exact_center,
                2 reduced_il# - ypart exact_center,
                2 reduced_il# + ypart exact_center);

  draw_brevis (exact_center + (3 reduced_slt#, 0),
               2 reduced_il#, reduced_il#, reduced_slt#);

  save xoffs, yoffs;

  xoffs# = xpart exact_center;
  yoffs# = ypart exact_center;

  define_pixels (xoffs, yoffs);

  save ellipse, pat, T;
  path ellipse, pat;
  transform T;

  T := identity xscaled stem_width
                yscaled blot_diameter;
  pickup pencircle transformed T;
  ellipse := fullcircle transformed T;

  lft x11 = lft x12 = xoffs;
  top y12 - bot y11 = 4 reduced_il;
  top y12 + bot y11 = 2 yoffs;
  x13 = x3;
  y13 = y11;
  rt x14 = rt x15 = w;
  y14 = y11;
  y15 = y12;

  pat := get_subpath (ellipse, down, up, z13)
         -- z3l{up}           % avoid FontForge problems by specifying
         .. z3r               % direction plus .. instead of --
         -- cycle;

  fill get_subpath (ellipse, down, up, z11)
       -- get_subpath (ellipse, up, down, z12)
       -- cycle;
  fill get_subpath (ellipse, down, up, z14)
       -- get_subpath (ellipse, up, down, z15)
       -- cycle;

  fill pat;
  fill pat xscaled -1
           shifted (w, 0);
  fill pat yscaled -1
           shifted (0, 2 yoffs);
  fill pat scaled -1
           shifted (w, 2 yoffs);

  labels (11, 12, 13, 14, 15);
enddef;


fet_beginchar ("neo-mensural C clef", "neomensural.c");
  draw_staff_if_debugging (-1, 3);
  draw_neomensural_c_clef ((0, 0), 1.0);
fet_endchar;


fet_beginchar ("neo-mensural C clef (reduced)", "neomensural.c_change");
  draw_neomensural_c_clef ((0, 0), .8);
fet_endchar;


def draw_petrucci_c_clef (expr exact_center, flare_align, reduction) =
  % inspired by Josquin Desprez, "Stabat Mater", Libro tertio,
  % 1519, printed by Petrucci, in: MGG, volume 7, Table 11.
  % Also by Petrucci's Canti C, Venedig 1503.  In: MGG, volume
  % 9, p. 1681/1682.

  save reduced_il, reduced_slt;

  reduced_il# = staff_space# * reduction;
  reduced_slt# = linethickness# * reduction;

  define_pixels (reduced_il);

  draw_double_brevis (exact_center + (0, 0.5 staff_space#),
                      reduced_il#, reduced_il#, reduced_slt#,
                      staff_space);

  save half_reduced_il, left_depth, left_height;

  half_reduced_il# = staff_space# * sqrt (reduction);
  left_height# = half_reduced_il# * min (3.2, 3.2 + 0.2 + flare_align);
  left_depth# = half_reduced_il# * min (3.2, 3.2 + 0.2 - flare_align);

  define_pixels (half_reduced_il);
  define_pixels (left_depth, left_height);

  set_char_box (0 - xpart exact_center,
                reduced_il# + xpart exact_center,
                left_depth# - ypart exact_center,
                left_height# + ypart exact_center);

  save xoffs, yoffs;

  xoffs# = xpart exact_center;
  yoffs# = ypart exact_center;

  define_pixels (xoffs, yoffs);

  save ellipse, T;
  path ellipse;
  transform T;

  T := identity xscaled 1.4 linethickness
                yscaled blot_diameter;
  pickup pencircle transformed T;
  ellipse := fullcircle transformed T;

  lft x11 = lft x13 = xoffs;
  top y11 = yoffs + left_height;
  bot y13 = yoffs - left_depth;
  rt x15 = rt x17 = xoffs + brevis_width;
  y15 = min (y11 - 0.2 half_reduced_il, yoffs + 2.2 half_reduced_il);
  y17 = max (y13 + 0.2 half_reduced_il, yoffs - 2.2 half_reduced_il);

  z12 = z14 yscaled -1;
  z14 = z6;
  z16 = z18 yscaled -1;
  rt z18 = lft z14 shifted (brevis_width, 0);

  penpos12 (1.4 linethickness, 0);
  penpos14 (1.4 linethickness, 0);
  penpos16 (1.4 linethickness, 0);
  penpos18 (1.4 linethickness, 0);

  if top y11 > -y6 + 0.7 linethickness:
    fill get_subpath (ellipse, up, down, z11)
         -- z12l{down}  % avoid FontForge problems by specifying
         .. z12r        % direction plus .. instead of --
         -- cycle;
  fi;
  if bot y13 < y6 - 0.7 linethickness:
    fill get_subpath (ellipse, down, up, z13)
         -- z14r{up}    % avoid FontForge problems by specifying
         .. z14l        % direction plus .. instead of --
         -- cycle;
  fi;
  if top y15 > -y6 + 0.7 linethickness:
    fill get_subpath (ellipse, up, down, z15)
         -- z16l{down}  % avoid FontForge problems by specifying
         .. z16r        % direction plus .. instead of --
         -- cycle;
  fi;
  if bot y17 < y6 - 0.7 linethickness:
    fill get_subpath (ellipse, down, up, z17)
         -- z18r{up}    % avoid FontForge problems by specifying
         .. z18l        % direction plus .. instead of --
         -- cycle;
  fi;

  labels (11, 13, 15, 17);
  penlabels (12, 14, 16, 18);
enddef;


fet_beginchar ("Petrucci C1 clef", "petrucci.c1");
  draw_staff_if_debugging (-1, 3);
  draw_petrucci_c_clef ((0, 0), +2, 1.0);
fet_endchar;


fet_beginchar ("Petrucci C1 clef (reduced)", "petrucci.c1_change");
  draw_petrucci_c_clef ((0, 0), +2, .8);
fet_endchar;


fet_beginchar ("Petrucci C2 clef", "petrucci.c2");
  draw_staff_if_debugging (-1, 3);
  draw_petrucci_c_clef ((0, 0), +1, 1.0);
fet_endchar;


fet_beginchar ("Petrucci C2 clef (reduced)", "petrucci.c2_change");
  draw_petrucci_c_clef ((0, 0), +1, .8);
fet_endchar;


fet_beginchar ("Petrucci C3 clef", "petrucci.c3");
  draw_staff_if_debugging (-1, 3);
  draw_petrucci_c_clef ((0, 0), 0, 1.0);
fet_endchar;


fet_beginchar ("Petrucci C3 clef (reduced)", "petrucci.c3_change");
  draw_petrucci_c_clef ((0, 0), 0, .8);
fet_endchar;


fet_beginchar ("Petrucci C4 clef", "petrucci.c4");
  draw_staff_if_debugging (-1, 3);
  draw_petrucci_c_clef ((0, 0), -1, 1.0);
fet_endchar;


fet_beginchar ("Petrucci C4 clef (reduced)", "petrucci.c4_change");
  draw_petrucci_c_clef ((0, 0), -1, .8);
fet_endchar;


fet_beginchar ("Petrucci C5 clef", "petrucci.c5");
  draw_staff_if_debugging (-1, 3);
  draw_petrucci_c_clef ((0, 0), -2, 1.0);
fet_endchar;


fet_beginchar ("Petrucci C5 clef (reduced)", "petrucci.c5_change");
  draw_petrucci_c_clef ((0, 0), -2, .8);
fet_endchar;


def draw_mensural_c_clef (expr exact_center, reduction, fill_char) =
  save reduced_il, vert_thick, hor_thick, blot_rad;

  reduced_il# = staff_space# * reduction;
  vert_thick# = linethickness# * 1.4;
  hor_thick# = staff_space# * reduction * 0.25;

  blot_rad = blot_diameter / 2;

  define_pixels (reduced_il, vert_thick, hor_thick);

  pickup pencircle scaled blot_diameter;

  penpos1 (vert_thick, 0);
  penpos2 (vert_thick, 0);
  penpos3 (hor_thick, 90);
  penpos4 (hor_thick, 90);
  penpos5 (hor_thick, 90);
  penpos6 (hor_thick, 90);
  penpos7 (vert_thick, 0);
  penpos8 (hor_thick, 90);

  z1l = (0, 0);
  x2l = 0;
  top y2 = 2.2 reduced_il;
  z3 = (vert_thick, 0.75 reduced_il);
  z4 = z3 + (reduced_il - vert_thick, 0);
  z5 = z4 + (vert_thick, -0.5 reduced_il);
  z6 = z5 - (reduced_il, 0);
  z7 = z4 + (0.5 vert_thick, 0.5 reduced_il);
  z8 = z5 - (vert_thick, 0);

  save pat, pat_mid;
  path pat, pat_mid;

  pat = z1l
        -- z2l{up}
        .. z2 + (0, blot_rad)
        .. {down}z2r
        -- top z3r{down}
        .. {right}rt z3r
        -- lft z4r{right}
        .. {up}top z4r
        -- z7l{up}
        .. z7 + (0, blot_rad)
        .. {down}z7r
        -- top z5l{down}
        .. {left}lft z5l
        -- rt z6l{left}
        .. {down}bot z6l
        --z1r;
  pat := pat
         -- reverse pat yscaled -1
         -- cycle;
  fill pat;

  if fill_char:
    pat_mid = bot z3l{up}
              .. {right}rt z3l
              -- lft z4l{right}
              .. {down}bot z4l
              -- top z8r{down}
              .. {left}lft z8r
              -- rt z6r{left}
              .. {up}top z6r
              --cycle;
    unfill pat_mid;

    pat_mid := pat_mid shifted (0, -reduced_il);
    unfill pat_mid;
  fi;

  set_char_box (0, reduced_il# + vert_thick#,
                2.2 reduced_il#, 2.2 reduced_il#);

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


fet_beginchar ("mensural C clef", "mensural.c");
  draw_staff_if_debugging (-1, 3);
  draw_mensural_c_clef ((0, 0), 1.0, true);
fet_endchar;


fet_beginchar ("mensural C clef (reduced)", "mensural.c_change");
  draw_mensural_c_clef ((0, 0), .8, true);
fet_endchar;


fet_beginchar ("black mensural C clef", "blackmensural.c");
  draw_staff_if_debugging (-1, 3);
  draw_mensural_c_clef ((0, 0), 1.0, false);
fet_endchar;


fet_beginchar ("black mensural C clef (reduced)", "blackmensural.c_change");
  draw_mensural_c_clef ((0, 0), 0.8, false);
fet_endchar;


def draw_diamond (expr exact_center, reduction) =
  save stem_width, reduced_nht, holeheight, beamheight;
  save rh_height, rh_width;

  stem_width# = 1.4 reduced_slt#;
  reduced_nht# = noteheight# * reduction;
  holeheight# = 3 reduced_slt#;
  beamheight# = 0.4 (reduced_nht# - holeheight#);

  rh_height# = 1.2 staff_space# * reduction;
  rh_width# / rh_height# = tand (30);

  define_pixels (beamheight, stem_width);
  define_pixels (rh_height, rh_width);

  save xoffs, yoffs;

  xoffs# = xpart exact_center;
  yoffs# = ypart exact_center;

  define_pixels (xoffs, yoffs);

  save ellipse, T;
  path ellipse;
  transform T;

  T := identity xscaled beamheight
                yscaled stem_width
                rotated 45;
  pickup pencircle transformed T;
  ellipse := reverse fullcircle transformed T;

  x21 := xoffs - rh_width / 2;
  y21 := yoffs;
  x22 := xoffs;
  y22 := yoffs + rh_height / 2;
  x23 := xoffs + rh_width / 2;
  y23 := yoffs;
  x24 := xoffs;
  y24 := yoffs - rh_height / 2;

  fill get_subpath (ellipse, z21 - z24, z22 - z21, z21)
       -- get_subpath (ellipse, z22 - z21, z23 - z22, z22)
       -- get_subpath (ellipse, z23 - z22, z24 - z23, z23)
       -- get_subpath (ellipse, z24 - z23, z21 - z24, z24)
       -- cycle;

  save l;
  path l[];

  l2122 := (directionpoint (z21 - z22) of ellipse) shifted z21
           -- (directionpoint (z21 - z22) of ellipse) shifted z22;
  l2223 := (directionpoint (z22 - z23) of ellipse) shifted z22
           -- (directionpoint (z22 - z23) of ellipse) shifted z23;
  l2324 := (directionpoint (z23 - z24) of ellipse) shifted z23
           -- (directionpoint (z23 - z24) of ellipse) shifted z24;
  l2421 := (directionpoint (z24 - z21) of ellipse) shifted z24
           -- (directionpoint (z24 - z21) of ellipse) shifted z21;

  unfill l2122 intersectionpoint l2223
         -- l2223 intersectionpoint l2324
         -- l2324 intersectionpoint l2421
         -- l2421 intersectionpoint l2122
         -- cycle;

  labels (21, 22, 23, 24);
enddef;


def draw_petrucci_f_clef (expr exact_center, reduction) =
  % inspired by L'homme arme super voces musicales in Misse
  % Josquin, 1502, Petrucci, in: MGG, volume 7, col. 200; also
  % inspired by Gaspar van Weerbeke, "Virgo Maria" (1502), in:
  % MGG, volume 9, col. 653 ("Motette"), fig. 3.; also by Andr'e
  % Campra, "Entr'ee des s'er'enades" (1710), in: MGG, volume 2,
  % col. 1649 ("Contredanse"), fig. 2.

  save interline, reduced_il, reduced_slt;

  interline# = staff_space#;
  reduced_il# = staff_space# * reduction;
  reduced_slt# = linethickness# * reduction;

  draw_brevis (exact_center, reduced_il#, reduced_il#, reduced_slt#);
  draw_diamond (exact_center
                + (1.6 interline# * reduction, interline# / 2),
                reduction);
  draw_diamond (exact_center
                + (1.6 interline# * reduction, -interline# / 2),
                reduction);

  define_pixels (interline, reduced_il, reduced_slt);

  save stem_width;

  stem_width# = 1.4 reduced_slt#;

  define_pixels (stem_width);

  save xoffs, yoffs;

  xoffs# = xpart exact_center;
  yoffs# = ypart exact_center;

  define_pixels (xoffs, yoffs);

  % brevis stem
  save ellipse, T;
  path ellipse;
  transform T;

  T := identity xscaled stem_width
                yscaled blot_diameter;
  pickup pencircle transformed T;
  ellipse := fullcircle transformed T;

  rt x8 = xoffs + reduced_il;
  y8 = y3;
  rt z9 = (xoffs + reduced_il, yoffs - 4 reduced_il);

  penpos8 (stem_width, 0);

  fill get_subpath (ellipse, down, up, z9)
       -- z8r
       -- z8l
       -- cycle;

  % upper diamond's stem
  z10 = (xoffs + 1.6 interline * reduction + stem_width / 2,
         yoffs + interline * reduction);
  top z11 = z10 + (0, 1.5 interline * reduction);

  penpos10 (stem_width, 0);

  fill get_subpath (ellipse, up, down, z11)
       -- z10l
       -- z10r
       -- cycle;

  % lower diamond's stem
  z12 = (xoffs + 1.6 interline * reduction - stem_width / 2,
         yoffs - interline * reduction);
  bot z13 = z12 + (0, -3.5 interline * reduction);

  penpos12 (stem_width, 0);

  fill get_subpath (ellipse, down, up, z13)
       -- z12r
       -- z12l
       -- cycle;

  save reduced_il, rh_height, rh_width;

  reduced_il# = staff_space# * reduction;
  rh_height# = 1.2 reduced_il#;
  rh_width# / rh_height# = tand (30);

  set_char_box (0 - xpart exact_center,
                1.6 interline# * reduction + 0.5 rh_width#
                + xpart exact_center,
                4.5 interline# * reduction - ypart exact_center,
                2.5 interline# * reduction + ypart exact_center);

  labels (9, 11, 13);
  penlabels (8, 10, 12);
enddef;


fet_beginchar ("Petrucci F clef", "petrucci.f");
  draw_staff_if_debugging (-1, 3);
  draw_petrucci_f_clef ((0, 0), 1.0);
fet_endchar;


fet_beginchar ("Petrucci F clef (reduced)", "petrucci.f_change");
  draw_petrucci_f_clef ((0, 0), .8);
fet_endchar;


def draw_mensural_f_clef (expr exact_center, reduction) =
  % inspired by Philippe le Duc, "Dite Signori" (1590), in: MGG,
  % volume 3, col. 848 ("Duc"); also by John Dowland, "The First
  % Booke of Songes" (1597), in: MGG, volume 3, col. 721
  % ("Dowland"), fig. 3.

  save width, reduced_slt, stem_width, dot_diameter;

  width# = 1.2 staff_space# * reduction;
  reduced_slt# = linethickness# * reduction;
  stem_width# = 1.4 reduced_slt#;
  dot_diameter# = 0.1 reduction * staff_space#;

  define_pixels (width, stem_width, staff_space, dot_diameter);

  save xoffs, yoffs;

  xoffs# = xpart exact_center;
  yoffs# = ypart exact_center;

  define_pixels (xoffs, yoffs);

  save ellipse, T;
  path ellipse;
  transform T;

  T := identity xscaled 0.2 width
                yscaled stem_width
                rotated 45;
  pickup pencircle transformed T;
  ellipse := fullcircle transformed T;

  % half circle
  lft z10 = (0, 0);

  save pat;
  path pat;

  pat := halfcircle scaled width
                    rotated -90
                    shifted (z10 - (xoffs, yoffs));

  z5 = point 0 of pat;
  z6 = point 1 of pat;
  z7 = point 2 of pat;
  z8 = point 3 of pat;
  z9 = point 4 of pat;

  save dirs;
  pair dirs[];

  dirs5 := direction 0 of pat;
  dirs6 := direction 1 of pat;
  dirs7 := direction 2 of pat;
  dirs8 := direction 3 of pat;
  dirs9 := direction 4 of pat;

  % we approximate `draw pat'
  fill get_subpath (ellipse, -dirs5, dirs5, z5)
       .. get_subpoint (ellipse, dirs6, z6)
       .. get_subpoint (ellipse, dirs7, z7)
       .. get_subpoint (ellipse, dirs8, z8)
       .. get_subpath (ellipse, dirs9, -dirs9, z9)
       .. get_subpoint (ellipse, -dirs8, z8)
       .. get_subpoint (ellipse, -dirs7, z7)
       .. get_subpoint (ellipse, -dirs6, z6)
       .. cycle;

  % upper dot
  rt x2 = xoffs + width;
  top y1 = yoffs + 0.5 width;
  z2 - z1 = (dot_diameter, -dot_diameter);

  fill get_subpath (ellipse, z1 - z2, z2 - z1, z1)
       -- get_subpath (ellipse, z2 - z1, z1 - z2, z2)
       -- cycle;

  % lower dot
  x3 = x1;
  top y1 - bot y4 = width;
  z4 - z3 = (dot_diameter, -dot_diameter);

  fill get_subpath (ellipse, z3 - z4, z4 - z3, z3)
       -- get_subpath (ellipse, z4 - z3, z3 - z4, z4)
       -- cycle;

  set_char_box (0 - xpart exact_center,
                width# + xpart exact_center,
                0.5 width# - ypart exact_center,
                0.5 width# + ypart exact_center);

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


fet_beginchar ("mensural F clef", "mensural.f");
  draw_staff_if_debugging (-1, 3);
  draw_mensural_f_clef ((0, 0), 1.0);
fet_endchar;


fet_beginchar ("mensural F clef (reduced)", "mensural.f_change");
  draw_mensural_f_clef ((0, 0), .8);
fet_endchar;


def draw_petrucci_g_clef (expr exact_center, reduction) =
  % inspired by Josquin Desprez, "Stabat Mater", Libro tertio,
  % 1519, printed by Petrucci, in: MGG, volume 7, Table 11.

  save reduced_il, reduced_slt;

  reduced_il# = staff_space# * reduction;
  reduced_slt# = linethickness# * reduction;
  define_pixels (reduced_il, reduced_slt);

  set_char_box (0 - xpart exact_center,
                1.25 reduced_il# + xpart exact_center,
                0.65 reduced_il# - ypart exact_center,
                3.80 reduced_il# + ypart exact_center);

  save xoffs, yoffs;

  xoffs# = xpart exact_center;
  yoffs# = ypart exact_center;

  define_pixels (xoffs, yoffs);

  save ellipse, paths, sub_path, outlines, sub_outlines, T;
  path ellipse, paths[], sub_path, outlines[], sub_outlines[];
  transform T;

  T := identity xscaled 0.5 reduced_slt
                yscaled 0.22 reduced_il
                rotated -35;
  pickup pencircle transformed T;
  ellipse := fullcircle transformed T;

  lft z1 = (xoffs + 0.80 reduced_il, yoffs + 0.00 reduced_il);
  lft z2 = (xoffs + 1.00 reduced_il, yoffs + 1.20 reduced_il);
  lft z3 = (xoffs + 0.70 reduced_il, yoffs + 2.00 reduced_il);
  lft z4 = (xoffs + 0.30 reduced_il, yoffs + 3.00 reduced_il);
  lft z5 = (xoffs + 0.80 reduced_il, yoffs + 3.70 reduced_il);
  lft z6 = (xoffs + 1.00 reduced_il, yoffs + 3.00 reduced_il);
  lft z7 = (xoffs + 0.60 reduced_il, yoffs + 2.00 reduced_il);
  lft z8 = (xoffs + 0.30 reduced_il, yoffs + 1.70 reduced_il);
  lft z9 = (xoffs + 0.00 reduced_il, yoffs + 0.75 reduced_il);
  lft z10 = (xoffs + 0.20 reduced_il, yoffs + 0.60 reduced_il);

  paths1 := z1{-1, 2}
            .. z2
            .. z3
            .. z4
            .. z5
            .. z6
            .. z7
            .. z8
            .. z9
            .. z10;

  save dirs, s;
  pair dirs[];

  s := 1/4;

  % we approximate `draw paths1'
  for i = 1 step s until (length paths1 + 1):
    dirs[i] := direction (i - 1) of paths1;
  endfor;

  outlines1 := get_subpath (ellipse, -dirs1, dirs1, z1)
               for i = (1 + s) step s until (length paths1 + 1 - s):
                 .. get_subpoint (ellipse, dirs[i],
                                  point (i - 1) of paths1)
               endfor
               .. get_subpath (ellipse, dirs10, -dirs10, z10)
               for i = (length paths1 + 1 - s) step -s until (1 + s):
                 .. get_subpoint (ellipse, -dirs[i],
                                  point (i - 1) of paths1)
               endfor
               .. cycle;

  save len;

  len := length outlines1;

  sub_outlines1 := subpath (0, floor (1/4 len)) of outlines1;
  sub_outlines2 := subpath (floor (1/4 len), floor (2/4 len)) of outlines1;
  sub_outlines3 := subpath (floor (2/4 len), floor (3/4 len)) of outlines1;
  sub_outlines4 := subpath (floor (3/4 len), len) of outlines1;

  save times;
  numeric times[];

  (times12, times21) = sub_outlines1 intersectiontimes sub_outlines2;
  (times13, times31) = sub_outlines1 intersectiontimes sub_outlines3;
  (times42, times24) = sub_outlines4 intersectiontimes sub_outlines2;
  (times43, times34) = sub_outlines4 intersectiontimes sub_outlines3;

  T := identity xscaled 0.75 reduced_slt
                yscaled 0.33 reduced_il
                rotated -35;
  pickup pencircle transformed T;
  ellipse := fullcircle transformed T;

  lft z21 = (xoffs + 1.05 reduced_il, yoffs + 0.45 reduced_il);
  lft z22 = (xoffs + 0.55 reduced_il, yoffs + 0.45 reduced_il);
  lft z23 = (xoffs + 0.55 reduced_il, yoffs - 0.45 reduced_il);
  lft z24 = (xoffs + 1.05 reduced_il, yoffs - 0.45 reduced_il);
  lft z25 = (xoffs + 1.10 reduced_il, yoffs + 0.00 reduced_il);
  lft z26 = (xoffs + 0.80 reduced_il, yoffs + 0.00 reduced_il);

  paths2 := z21
            .. z22
            .. z23
            .. z24
            .. {up}z25
            -- z26;

  sub_path := subpath (0, 1) of paths2;

  times1 = xpart (sub_outlines1 intersectiontimes sub_path);
  times4 = xpart (sub_outlines4 intersectiontimes sub_path);

  % we have to find the envelope intersections (if any)
  save t;
  numeric t[];

  t1 = find_envelope_cusp (reverse ellipse,
                           subpath (1, 2) of paths2,
                           1/256) + 1;
  if t1 < 1:
    t1 := 1;
    t2 := 1;
  else:
    t2 = find_envelope_cusp (ellipse,
                             subpath (3, 4) of reverse paths2,
                             1/256) + 3;
    t2 := length paths2 - t2;
  fi;

  t3 = find_envelope_cusp (reverse ellipse,
                           subpath (2, 4 - epsilon) of paths2,
                           1/256) + 2;
  if t3 < 2:
    t3 := 3;
    t4 := 3;
  else:
    t4 = find_envelope_cusp (ellipse,
                             subpath (1 + epsilon, 3) of reverse paths2,
                             1/256) + 1;
    t4 := length paths2 - t4;
  fi;

  fill subpath (times1 + s / 4, times13) of sub_outlines1
       -- subpath (times31, infinity) of sub_outlines3
       & subpath (0, times42) of sub_outlines4
       -- subpath (times24, infinity) of sub_outlines2
       & subpath (0, times34) of sub_outlines3
       -- subpath (times43, times4 - s / 4) of sub_outlines4
       -- cycle;
  unfill subpath (times12, infinity) of sub_outlines1
         & subpath (0, times21) of sub_outlines2
         -- cycle;
  fill subpath (times4 + s / 4, infinity) of sub_outlines4
       & subpath (0, times1 - s / 4) of sub_outlines1
       -- cycle;


  % we approximate `draw paths2'
  for i = 1 step s until (length paths2 - s):
    dirs[i + 20] := direction (i - 1) of paths2;
  endfor;

  sub_outlines21 := get_subpath (ellipse, -dirs21, dirs21, z21)
                    for i = (1 + s) step s until (length paths2 - s):
                      .. get_subpoint (ellipse, dirs[i + 20],
                                       point (i - 1) of paths2)
                    endfor
                    .. get_subpath (ellipse, up, z26 - z25, z25);
  sub_outlines22 := get_subpath (ellipse, z26 - z25, z25 - z26, z26)
                    -- get_subpoint (ellipse, z25 - z26, z25);
  sub_outlines23 := get_subpoint (ellipse, down, z25)
                    for i = (length paths2 - s) step -s until (t4 + 1):
                      .. get_subpoint (ellipse, -dirs[i + 20],
                                       point (i - 1) of paths2)
                    endfor
                    .. get_subpoint (ellipse, -direction t4 of paths2,
                                     point t4 of paths2);
  sub_outlines24 := get_subpoint (ellipse, -direction t3 of paths2,
                                  point t3 of paths2)
                    for i = (floor (t3 / s) * s + 1) step -s until (t2 + 1):
                      .. get_subpoint (ellipse, -dirs[i + 20],
                                       point (i - 1) of paths2)
                    endfor
                    .. get_subpoint (ellipse, -direction t2 of paths2,
                                     point t2 of paths2);
  sub_outlines25 := get_subpoint (ellipse, -direction t1 of paths2,
                                  point t1 of paths2)
                    for i = (floor (t1 / s) * s + 1) step -s until (1 + s):
                      .. get_subpoint (ellipse, -dirs[i + 20],
                                       point (i - 1) of paths2)
                    endfor;

  (times2223, times2322) = sub_outlines22 intersectiontimes sub_outlines23;
  (times2324, times2423) = sub_outlines23 intersectiontimes sub_outlines24;
  (times2425, times2524) = sub_outlines24 intersectiontimes sub_outlines25;

  fill sub_outlines21
       -- subpath (0, times2223) of sub_outlines22
       -- subpath (times2322, times2324) of sub_outlines23
       -- subpath (times2423, times2425) of sub_outlines24
       -- subpath (times2524, infinity) of sub_outlines25
       .. cycle;

  labels (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
  labels (21, 22, 23, 24, 25, 26);
enddef;


fet_beginchar ("Petrucci G clef", "petrucci.g");
  draw_staff_if_debugging (-1, 3);
  draw_petrucci_g_clef ((0, 0), 1.0);
fet_endchar;


fet_beginchar ("Petrucci G clef (reduced)", "petrucci.g_change");
  draw_petrucci_g_clef ((0, 0), .8);
fet_endchar;

def draw_mensural_g_clef (expr exact_center, reduction) =
  % TODO: Rewrite me.  The former mensural g clef looked ugly, and the
  % code was removed when it broke for small font sizes after some
  % global changes in the font.  Currently, the character is mapped to
  % a copy of the petrucci g clef (which, after all, *is* a mensural g
  % clef, but not the one that we have in mind here). -- jr
  %
  % Possible sources of inspiration for this clef include: Francisco
  % Guerrero, "Lib. 1.  Missarum" (1566), in: MGG, volume 3, col. 858
  % ("Ducis"); Stefano Fabri, "Quam speciosa veteranis" (1611), in:
  % MGG, volume 3, col. 1698 ("Fabri"); Philippus Dulichius,
  % "Fasciculus novus ..."  (1598), in: MGG, volume 3, col. 919
  % ("Dulichius"), fig. 1; Noe Faignient, "Ic sal de Heer myn God
  % gebenedye" (1568), in: MGG, volume 3, col. 1735 ("Faignient").
enddef;


%
% FIXME: This clef is preliminarily mapped to the petrucci g clef
% until the code for the mensural g clef will be rewritten.
%
fet_beginchar ("mensural G clef", "mensural.g");
  draw_staff_if_debugging (-1, 3);
  draw_petrucci_g_clef ((0, 0), 1.0);
fet_endchar;


fet_beginchar ("mensural G clef (reduced)", "mensural.g_change");
  draw_petrucci_g_clef ((0, 0), .8);
fet_endchar;



%%%%%%%%
%
%
%
% Hufnagel
%
%
%
def draw_hufnagel_do_clef (expr exact_center, reduction) =
  % inspired by Graduale of Friedrich Zollner (1442), in: MGG,
  % volume 9, col. 1413 ("Neustift"), fig. 1.

  save reduced_il;

  reduced_il# = staff_space# * reduction;

  define_pixels (reduced_il);

  set_char_box (0 - xpart exact_center,
                1.10 reduced_il# + xpart exact_center,
                0.70 reduced_il# - ypart exact_center,
                0.75 reduced_il# + ypart exact_center);

  save xoffs, yoffs;

  xoffs# = xpart exact_center;
  yoffs# = ypart exact_center;

  define_pixels (xoffs, yoffs);

  save ellipse, pat, T;
  path ellipse, pat;
  transform T;

  T := identity xscaled 0.6 reduced_il
                yscaled 0.1 reduced_il
                rotated 40;
  pickup pencircle transformed T;
  ellipse := fullcircle transformed T;

  z1 = (xoffs + 0.90 reduced_il, yoffs + .45 reduced_il);
  z2 = (xoffs + 0.80 reduced_il, yoffs + .45 reduced_il);
  z3 = (xoffs + 0.50 reduced_il, yoffs + .60 reduced_il);
  z4 = (xoffs + 0.20 reduced_il, yoffs + .45 reduced_il);
  z5 = (xoffs + 0.20 reduced_il, yoffs - .45 reduced_il);
  z6 = (xoffs + 0.40 reduced_il, yoffs - .55 reduced_il);

  pat := z1
         .. z2
         .. z3
         -- z4
         -- z5
         -- z6;

  fill get_subpath (ellipse, -direction 0 of pat, direction 0 of pat, z1)
       .. get_subpoint (ellipse, direction 1 of pat, z2)
       .. get_subpath (ellipse, direction (2 - epsilon) of pat, z4 - z3, z3)
       -- get_subpath (ellipse, z4 - z3, z5 - z4, z4)
       -- get_subpath (ellipse, z5 - z4, z6 - z5, z5)
       -- get_subpath (ellipse, z6 - z5, z5 - z6, z6)
       -- get_subpoint (ellipse, z5 - z6, z5)
       -- get_subpoint (ellipse, z4 - z5, z5)
       -- get_subpoint (ellipse, z4 - z5, z4)
       -- get_subpoint (ellipse, -direction (2 - epsilon) of pat, z3)
       .. get_subpath (ellipse, -direction 1 of pat, -direction 1 of pat, z2)
       .. cycle;

  labels (1, 2, 3, 4, 5, 6);
enddef;


fet_beginchar ("Hufnagel Do clef", "hufnagel.do");
  draw_staff_if_debugging (-1, 3);
  draw_hufnagel_do_clef ((0, 0), 1.0);
fet_endchar;


fet_beginchar ("Hufnagel Do clef (reduced)", "hufnagel.do_change");
  draw_hufnagel_do_clef ((0, 0), .8);
fet_endchar;


def draw_hufnagel_fa_clef (expr exact_center, reduction) =
  % inspired by Bamberger Manuscript (15th century), in:
  % MGG, volume 2, table 59.

  save reduced_il;

  reduced_il# = staff_space# * reduction;

  define_pixels (reduced_il);

  set_char_box (0 - xpart exact_center,
                1.20 reduced_il# + xpart exact_center,
                1.15 reduced_il# - ypart exact_center,
                1.00 reduced_il# + ypart exact_center);

  save xoffs, yoffs;

  xoffs# = xpart exact_center;
  yoffs# = ypart exact_center;

  define_pixels (xoffs, yoffs);

  save ellipse, pat, T;
  path ellipse, pat;
  transform T;

  T := identity xscaled 0.6 reduced_il
                yscaled 0.1 reduced_il
                rotated 40;
  pickup pencircle transformed T;
  ellipse := fullcircle transformed T;

  z11 = (xoffs + 0.90 reduced_il, yoffs + 0.70 reduced_il);
  z12 = (xoffs + 0.80 reduced_il, yoffs + 0.70 reduced_il);
  z13 = (xoffs + 0.50 reduced_il, yoffs + 0.85 reduced_il);
  z14 = (xoffs + 0.20 reduced_il, yoffs + 0.70 reduced_il);
  z15 = (xoffs + 0.20 reduced_il, yoffs - 1.10 reduced_il);

  pat := z11
         .. z12
         .. z13
         -- z14
         -- z15;

  fill get_subpath (ellipse, -direction 0 of pat, direction 0 of pat, z11)
       .. get_subpoint (ellipse, direction 1 of pat, z12)
       .. get_subpath (ellipse, direction (2 - epsilon) of pat, z14 - z13,
                       z13)
       -- get_subpath (ellipse, z14 - z13, z15 - z14, z14)
       -- get_subpath (ellipse, z15 - z14, z14 - z15, z15)
       -- get_subpoint (ellipse, z14 - z15, z14)
       -- get_subpoint (ellipse, -direction (2 - epsilon) of pat, z13)
       .. get_subpath (ellipse, -direction 1 of pat, -direction 1 of pat, z12)
       .. cycle;

  z16 = (xoffs + 0.90 reduced_il, yoffs - 0.05 reduced_il);
  z17 = (xoffs + 0.80 reduced_il, yoffs - 0.05 reduced_il);
  z18 = (xoffs + 0.50 reduced_il, yoffs + 0.10 reduced_il);
  z19 = (xoffs + 0.20 reduced_il, yoffs - 0.05 reduced_il);

  pat := z16
         .. z17
         .. z18
         -- z19;

  fill get_subpath (ellipse, -direction 0 of pat, direction 0 of pat, z16)
       .. get_subpoint (ellipse, direction 1 of pat, z17)
       .. get_subpath (ellipse, direction (2 - epsilon) of pat, z19 - z18,
                       z18)
       -- get_subpoint (ellipse, z19 - z18, z19)
       -- get_subpoint (ellipse, -direction (2 - epsilon) of pat, z18)
       .. get_subpoint (ellipse, -direction 1 of pat, z17)
       .. cycle;

  labels (11, 12, 13, 14, 15, 16, 17, 18, 19);
enddef;


fet_beginchar ("Hufnagel Fa clef", "hufnagel.fa");
  draw_staff_if_debugging (-1, 3);
  draw_hufnagel_fa_clef ((0, 0), 1.0);
fet_endchar;


fet_beginchar ("Hufnagel Fa clef (reduced)", "hufnagel.fa_change");
  draw_hufnagel_fa_clef ((0, 0), .8);
fet_endchar;


def draw_hufnagel_do_fa_clef (expr exact_center, reduction) =
  draw_hufnagel_do_clef (exact_center, reduction);
  draw_hufnagel_fa_clef (exact_center + (0, -2 staff_space#), reduction);

  set_char_box (0 - xpart exact_center,
                1.20 reduced_il# + xpart exact_center,
                1.15 reduced_il# + 2 staff_space# - ypart exact_center,
                0.75 reduced_il# + ypart exact_center);
enddef;


fet_beginchar ("Hufnagel Do/Fa clef", "hufnagel.do.fa");
  draw_staff_if_debugging (-1, 3);
  draw_hufnagel_do_fa_clef ((0, 0), 1.0);
fet_endchar;


fet_beginchar ("Hufnagel Do/Fa clef (reduced)", "hufnagel.do.fa_change");
  draw_hufnagel_do_fa_clef ((0, 0), .8);
fet_endchar;


%%%%%%%%
%%
%% Medieval East-Slavic (Kievan) Notation clefs
%% Code by Aleksandr Andreev <aleksandr.andreev@gmail.com>
%%
%%%%%%%%

def draw_kievan_do_clef =
  z1 = (1.108 staff_space, 0.554 staff_space);
  z2 = (1.063 staff_space, -0.122 staff_space);
  z3 = (1.467 staff_space, -1.621 staff_space);
  z4 = (1.002 staff_space, -2.253 staff_space);

  y5 = y3;
  x4 - x5 = x3 - x4;

  z6 = (0.917 staff_space, -0.383 staff_space);
  z7 = (0.012 staff_space, -0.448 staff_space);
  z8 = (0, -0.167 staff_space);
  z9 = (0.057 staff_space, 0.464 staff_space);
  z10 = (0.994 staff_space, 0.387 staff_space);
  z11 = (1.023 staff_space, 0.554 staff_space);

  fill z1
       .. z2{down}
       .. z3
       -- z4
       -- z5
       .. {up}z6
       & z6{left}
       .. z7
       & z7
       .. z8{up}
       .. z9
       & z9
       .. {right}z10
       & z10
       .. z11
       -- cycle;

  set_char_box (0, 1.5 staff_space#,
                2.25 staff_space#, 0.55 staff_space#);
enddef;


fet_beginchar ("Kievan tsefaut clef", "kievan.do");
  % This draws the Tse-Fa-Ut clef; it is a variant alto clef that
  % always occurs on the third line of the staff.
  draw_kievan_do_clef;
fet_endchar;


fet_beginchar ("Kievan tsefaut clef (change)", "kievan.do_change");
  % This is the same thing as a do clef?
  draw_kievan_do_clef;
fet_endchar;

fet_endgroup ("clefs");
