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

%
% The stems of the natural are brushed (at least, in Barenreiter SCS)
%

% general parameters:
save stem_thickness, stem_end_thickness_multiplier;
save beam_thickness, beam_slant;

stem_thickness# := 0.09 staff_space# + 0.5 stafflinethickness#;
stem_end_thickness_multiplier := 10/7;
beam_slant := 1.266 stafflinethickness;
beam_thickness := 0.485 staff_space -  stafflinethickness;


def draw_natural (expr arrowup, arrowdown, figured_bass) =
  save depth, height, width, breapth;
  save full_width, full_height;
  save offset;
  save hole_highest_point;
  save upstem_factor, downstem_factor;
  save upstem_end_thickness, downstem_end_thickness;
  save half_height, half_box_height;
  save beam_direction, r_stem_top_path, l_stem_bottom_path;
  pair beam_direction;
  path r_stem_top_path, l_stem_bottom_path;

  upstem_factor = downstem_factor = stem_end_thickness_multiplier;

  if figured_bass:
    full_height# := number_design_size + 2 figbass_y#;
    full_width# := .7 figbass_width#;
    offset# := .5 number_design_size;
    width# := figbass_width#;

    hole_highest_point := 0.2 staff_space + stafflinethickness;
  else:
    full_height# := 3 staff_space#;
    full_width# := 2/3 staff_space#;
    offset# := 0;
    width# := full_width#;

    hole_highest_point := 0.5 (staff_space - stafflinethickness);
  fi;
  define_pixels (offset);

  half_height# := 0.5 full_height#;
  define_pixels (half_height);
  define_whole_pixels (full_width);

  depth# := half_height# - offset#;
  height# := half_height# + offset#;
  breapth# := 0;

  if arrowup:
    % synchronized with point z4 of the arrow
    height# := half_height#                               % y1
               + .1 staff_space# + .5 stafflinethickness# % upshift
               + .85 staff_space# + stafflinethickness#;  % htip
    breapth# := .3 staff_space# - .5 stem_thickness#;
    % to look nice, arrowed stems must be less brushed
    upstem_factor := 0.5 (1 + upstem_factor);
  fi;
  if arrowdown:
    % synchronized with point z4 of the arrow
    depth# := half_height#                               % y3
              + .1 staff_space# + .5 stafflinethickness# % upshift
              + .85 staff_space# + stafflinethickness#;  % htip
    width# := width# + .3 staff_space# - .5 stem_thickness#;
    % to look nice, arrowed stems must be less brushed
    downstem_factor := 0.5 (1 + downstem_factor);
  fi;

  set_char_box (breapth#, width#, depth#, height#);
  d := d - feta_space_shift;

  upstem_end_thickness# = upstem_factor * stem_thickness#;
  downstem_end_thickness# = downstem_factor * stem_thickness#;
  define_whole_blacker_pixels (upstem_end_thickness, downstem_end_thickness);
  define_whole_blacker_pixels (stem_thickness);

  if odd (upstem_end_thickness - stem_thickness):
    upstem_end_thickness := upstem_end_thickness - 1;
  fi;
  if odd (downstem_end_thickness - stem_thickness):
    downstem_end_thickness := downstem_end_thickness - 1;
  fi;

  half_box_height := hole_highest_point + beam_thickness
                     %% correction for the fact that x11 != x12.
                     %% ideally y2 should be calculated from y11
                     %% and beam_thickness, but the brushed stems
                     %% would cause a cyclic dependency:
                     %% y2 -> x11 -> y14 -> y13 -> y12 -> y2
                     + 0.5 stem_thickness * beam_slant / full_width;

  %% stems:

  pickup pencircle scaled stem_thickness;

  penpos1 (upstem_end_thickness, 0);
  penpos3 (downstem_end_thickness, 0);
  penpos2 (stem_thickness, 0);
  penpos4 (stem_thickness, 0);

  x2r = w - (w - full_width) / 2;
  x4l = (w - full_width) / 2;
  x3 = x2;
  x1 = x4;

  y1 = half_height + offset;
  y3 = -half_height + offset;
  top y2 = vround (half_box_height + offset);
  bot y4 = vround (-half_box_height + offset) + feta_space_shift;

  l_stem_bottom_path := z4r{z4r - z1r}
                        .. bot z4
                        .. z4l{z1l - z4l};

  r_stem_top_path := z2r{z2r - z3r}
                     .. top z2
                     .. z2l{z3l - z2l};

  fill simple_serif (z1l, z1r, -30)
       -- l_stem_bottom_path
       -- cycle;

  fill simple_serif (z3l, z3r, 30)
       -- r_stem_top_path
       -- cycle;

  %% beams:

  beam_direction = (full_width, beam_slant);

  z11 = z3l + whatever * (z2l - z3l);
  y11 = vround (hole_highest_point + offset);
  z12 = directionpoint -beam_direction of r_stem_top_path;
  z13 = z12 + whatever * beam_direction;
  x13 = x1;
  z14 = z11 + whatever * beam_direction;
  x14 = x1;

  z21 = z4r + whatever * (z1r - z4r);
  y21 = vround (-hole_highest_point + offset) + feta_space_shift;
  z22 = directionpoint -beam_direction of l_stem_bottom_path;
  z23 = z22 + whatever * beam_direction;
  x23 = x3;
  z24 = z21 + whatever * beam_direction;
  x24 = x3;

  fill z11
       -- z12
       -- z13
       -- z14
       -- cycle;

  fill z21
       -- z22
       -- z23
       -- z24
       -- cycle;

  if arrowup:
    fill draw_arrow (z1, upstem_end_thickness,
                     z1l - z4l, stafflinethickness / 2, false)
         -- cycle;
  fi;
  if arrowdown:
    fill draw_arrow (z3, downstem_end_thickness,
                     z2r - z3r, stafflinethickness / 2, true)
         -- cycle;
  fi;

  %% debugging:
  penlabels (1, 2, 3, 4);
  labels (11, 12, 13, 14, 21, 22, 23, 24);
  draw_staff_if_debugging (-2, 2);
enddef;


fet_beginchar ("natural", "natural");
  draw_natural (false, false, false);
fet_endchar;


fet_beginchar ("figured bass natural", "natural.figbass");
  draw_natural (false, false, true);
fet_endchar;


fet_beginchar ("arrowed natural (arrow up)", "natural.arrowup");
  draw_natural (true, false, false);
fet_endchar;


fet_beginchar ("arrowed natural (arrow down)", "natural.arrowdown");
  draw_natural (false, true, false);
fet_endchar;


fet_beginchar ("arrowed natural (arrows up and down)", "natural.arrowboth");
  draw_natural (true, true, false);
fet_endchar;
