% Feta (not the Font-En-Tja) music font -- global parameters for both feta and parmesan fonts
% This file is part of LilyPond, the GNU music typesetter.
%
% Copyright (C) 1997--2023 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 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/>.

stafflines := 5;

%
% The design size of a staff should really be the
% staff_space, but we use staffsize for historical reasons.
%

staff_space# := staffsize# / (stafflines - 1);
staff_space_rounded# := staff_space#;


%
% Measuring on pocket scores turns out: stafflinethickness is
% largely independent on staff size, and generally about 0.5 pt.
%
% By request of WL, we tune down the blackness a little
% for increased contrast with beams.
%

%% !! synchronize with paper.scm

save fixed_line_thickness, variable_line_factor;
fixed_line_thickness + variable_line_factor * 5 pt# = 0.50 pt#;
fixed_line_thickness + variable_line_factor * 4.125 pt# = 0.47 pt#;

stafflinethickness# := fixed_line_thickness
                       + variable_line_factor * staff_space#;
stafflinethickness_rounded# := stafflinethickness#;

%
% The following tunes the general blackness of the glyphs.
%

linethickness# := stafflinethickness#;                %% 0.5 pt#;
linethickness_rounded# := linethickness#;

%
% bigger puff_up_factor, relatively thicker stafflines.
%
%   20 pt = puff_up_factor 0
%   10 pt = puff_up_factor 1
%

puff_up_factor = (linethickness# - 0.1 staff_space#) / (0.1 staff_space#);


stemthickness# := 1.3 stafflinethickness#;
stemthickness_rounded# := stemthickness#;
ledgerlinethickness# := 2 stafflinethickness#;
ledgerlinethickness_rounded# := ledgerlinethickness#;

define_pixels (staff_space, stemthickness, stafflinethickness,
               ledgerlinethickness, linethickness);
define_whole_pixels (staff_space_rounded);
define_whole_blacker_pixels (stemthickness_rounded);
define_whole_vertical_blacker_pixels (stafflinethickness_rounded,
                                      ledgerlinethickness_rounded,
                                      linethickness_rounded);

if ledgerlinethickness_rounded > 2 stafflinethickness_rounded:
  ledgerlinethickness_rounded := 2 stafflinethickness_rounded;
fi;

%
% Because of the engraving/stamping process, no traditional
% characters have sharp edges and corners.
% The following variable controls the amount of `roundness'.
%
% This is not a meta variable: it is related to absolute sizes.
%
% FIXME: According to [Wanske], only outside corners should be round
%        I don't think we do this anywhere -- jcn
%

blot_diameter# = .40 pt#;
if (blot_diameter# * hppp) < 1:
  blot_diameter# := 1 / hppp;
fi
if (blot_diameter# * vppp) < 1:
  blot_diameter# := 1 / vppp;
fi

define_pixels (blot_diameter);


%
% symmetry
% --------
%
% Some glyphs have to be positioned exactly between stafflines (clefs,
% note heads).  This needs some care at lower resolutions.
%
% Most glyphs use the staffline thickness and the space between two
% staff lines as the fundamental parameters.  The latter is the distance
% between the middle of one staff line to the middle of the next.  To
% say it differently, the value `staff_space' is the sum of one staff line
% thickness and the whitespace between two adjacent staff lines.
%
% Normally, feta's vertical origin for glyphs is either the middle
% between two staff lines or the middle of a staff line.  For example, the
% lower edge of the central staff line is at the vertical position
% `-<staffline thickness> / 2', and the upper edge at
% `<staffline thickness> / 2'.  Here we need a value rounded to an integer
% (the feta code uses `stafflinethickness_rounded' for that purpose).
%
% If we have an odd number of pixels as the staffline thickness, Metafont
% rounds `-stafflinethickness_rounded / 2' towards zero and
% `stafflinethickness_rounded / 2' towards infinity.  Example: `round -1.5'
% yields -1, `round 1.5' yields 2.  The whitespace between staff lines is
% handled similarly.  If we assume that stafflinethickness_rounded is odd,
% we have the following cases:
%
% o The glyph is centered between three stafflines or five stafflines
%   (clef, `c' meter).  We have this:
%
%          ___________  a
%          ___________  1
%          ___________  a
%
%                            whitespace
%
%          ___________  a
%   ...... ___________  1 ..................  x axis
%          ___________  a
%
%                            whitespace
%
%          ___________  a
%          ___________  1
%          ___________  a
%
%   As can be seen, we get symmetry if we split staff lines into two
%   equal parts `a' and a pixel line with thickness 1.  Consequently, we
%   use the following algorithm:
%
%   . Decrease the height `h' by 1 temporarily.
%
%   . Compute the path for the upper half of the glyph.
%
%   . Mirror the path at the x axis.
%
%   . Shift the upper half one pixel up and connect it with the lower path.
%
%   . Restore height and decrease `d' by 1.
%
% o The glyph is centered between two or four staff lines, and the origin is
%   the middle of the whitespace.  Assuming that the whitespace consists of
%   an odd number of pixels, we have this:
%
%          -----------
%                       b
%                       1
%                       b
%          ___________
%                       b
%   ..................  1  .................  x axis
%                       b
%          ___________
%                       b
%                       1
%                       b
%          ___________
%
%   For symmetrical glyphs, this leads to a similar algorithm as above.
%   Glyphs which can't be constructed from an upper and lower part need
%   to be handled differently, namely to shift up the vertical center by
%   half a pixel:
%
%          ___________
%                       b
%
%                       0.5
%   ..................  0.5 ................  x axis
%
%                       b
%          ___________
%

feta_eps := 0;
feta_shift := 0;
feta_space_shift := 0;

% Use this for paths with a slant of 45 degrees to assure that
% the middle point of a penpos gets covered.
pair feta_offset;
feta_offset := (0, 0);

if known miterlimit:
  pickup nullpen;
else:
  feta_eps := eps;

  if odd stafflinethickness_rounded:
    feta_shift := 1;
  fi;

  if odd (staff_space_rounded - stafflinethickness_rounded):
    feta_space_shift := 1;
  fi;

  feta_offset := (0.5, 0.5);

  pickup pencircle scaled 1;
fi;

feta_fillpen := savepen;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Notehead width and height are defined here.
%
%
% Slope of slash.  From scm/grob-description.scm.  How to auto-copy?
slash_slope := 1.7;

% Thickness of slash lines.  Quarter notes get 1.5slt width.
slash_thick# := 2/3 * 0.48 staff_space#;

%
% Hand-engraved music often has balls extending above and below
% the lines.  If you like that, modify overdone heads (unit:
% stafflinethickness).
%

%% FIXME
% There is a problem with noteheads slightly extending beyond the staff
% lines.  This is due to the fact that staff_space + stafflinethickness
% is sometimes an odd number, so the nothead height and depth are not
% integers.  Then, when the font is converted to an outline font, the
% system rounds up the 0.5 left over from dividing the notehead height
% in two, and the notehead extends slightly beyond the staff line.
% In order to resolve this problem, we use overdone_heads to slightly
% reduce the notehead height.  Empirically, we have determined that
% reducing by 10% of stafflinethickness solves the problem.

overdone_heads = -0.1;
noteheight# := staff_space# + (1 + overdone_heads) * stafflinethickness#;

define_pixels (slash_thick);
define_whole_vertical_pixels (noteheight);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% This is used to draw all elliptical notes; it also sets
% `black_notehead_width` globally, so it should be called in any file
% that needs the value of `black_notehead_width`.
%
% SLANT moves both extrema on the long axis (by SLANT * ELLIPTICITY,
% so SLANT = -1 puts the extremum on the long axis next to the short
% axis one).
%
% OFFSET is needed for breves and longae only; it doesn't influence
% `width#` and `width`.
%

def draw_outside_ellipse (expr ellipticity, tilt, superness, slant, offset) =
  save attachment_y;
  save pat;
  path pat;

  pat := superellipse ((ellipticity, 0), (-slant * ellipticity, 1.0),
                       (-ellipticity, 0), (slant * ellipticity, -1.0),
                       superness);
  pat := pat rotated tilt;

  save top_point, right_point;
  pair top_point, right_point;

  top_point := directionpoint left of pat;
  right_point := directionpoint up of pat;

  save scaling, width;

  scaling# := noteheight# / (2 ypart (top_point));
  width# := 2 xpart (right_point) * scaling#;
  define_pixels (scaling);
  define_whole_pixels (width);

  set_char_box (0, width#, noteheight# / 2, noteheight# / 2);

  d := d - feta_space_shift;

  % attachment Y
  charwy := ypart (right_point) * scaling#;
  charwx := width#;

  pat := pat scaled scaling shifted (w / 2 + offset, .5 (h - d));

  if test_outlines = 1:
    draw pat;
  else:
    fill pat;
  fi;
enddef;


def draw_quarter_path =
  draw_outside_ellipse (1.49 - puff_up_factor / 3.0, 31, 0.707, 0, 0);
enddef;

test_outlines := 0;
draw_quarter_path;
black_notehead_width# := charwd;

define_pixels (slash_thick);
define_whole_vertical_pixels (noteheight);
