% Feta (not the Font-En-Tja) music font -- macros for parmesan font % This file is part of LilyPond, the GNU music typesetter. % % Copyright (C) 2001--2015 Juergen Reuter % % % 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 . % % Find point on `curve' which gives the tangent between point `p' % and `curve'. To guide the search, two auxiliary points must be % specified, `p_in' and `p_out'. The line between `p' and `p_in' % must intersect `curve', while the line between `p' and `p_out' % must not. % def find_tangent (expr p, curve, p_in, p_out) = begingroup; save mid, t, t_good, in, out; pair mid, in, out; in := p_in; out := p_out; forever: mid := 0.5 [in, out]; exitif abs (out - mid) <= eps; t := xpart (curve intersectiontimes (p -- mid)); if t > 0: in := mid; t_good := t; else: out := mid; fi; endfor; point t_good of curve endgroup enddef; % % Shift `curve' along the line given by the auxiliary points `p_in' % and `p_out' until `line' is a tangent, and return the shift. % If `curve' is shifted to position `p_in', it must intersect % `line', while shifted to `p_out' it must not. % def find_tangent_shift (expr line, curve, p_in, p_out) = begingroup; save mid, t, in, out; pair mid, in, out; in := p_in; out := p_out; forever: mid := 0.5 [in, out]; exitif abs (out - mid) <= eps; t := xpart ((curve shifted mid) intersectiontimes line); if t > 0: in := mid; else: out := mid; fi; endfor; mid endgroup enddef; % % Get subpath specified by `dir_in' and `dir_out' of `curve' % which is then shifted by `offset'. Assure that result has % the same orientation as `curve'. % def get_subpath (expr curve, dir_in, dir_out, offset) = begingroup; save t_in, t_out; t_in := directiontime dir_in of curve; t_out := directiontime dir_out of curve; if t_in > t_out: t_out := t_out + length curve; fi; (subpath (t_in, t_out) of curve) shifted offset endgroup enddef; % % Get point specified by `dir_' of `curve' which is then % shifted by `offset'. % def get_subpoint (expr curve, dir_, offset) = (directionpoint dir_ of curve) shifted offset enddef; % % This is the same as `get_subpath', except that the time values % used to construct the resulting subpath are rounded to integers. % def get_subpath_i (expr curve, dir_in, dir_out, offset) = begingroup; save t_in, t_out; t_in := directiontime dir_in of curve; t_out := directiontime dir_out of curve; if t_in > t_out: t_out := t_out + length curve; fi; (subpath (floor (t_in + 0.5), floor (t_out + 0.5)) of curve) shifted offset endgroup enddef; % % Find envelope cusp created by `object' moved along `curve', using % step value `s' for initial intermediate points. `s' must be small % enough so that this macro finds at least one point on the envelope % between the `entrance' and `exit' points of the cusp which has % a significantly different direction vector. % % This function returns a time value on `curve'; if there is no % cusp, it returns -1. % def find_envelope_cusp (expr object, curve, s) = begingroup; save mid, p, t, t_good, delta, start, stop, do_exit; pair p[]; boolean do_exit; p0 := (directionpoint (direction 0 of curve) of object) shifted (point 0 of curve); p1 := (directionpoint (direction s of curve) of object) shifted (point s of curve); t := s; forever: t := t + s; exitif t >= length curve; p2 := (directionpoint (direction t of curve) of object) shifted (point t of curve); if p2 <> p1: delta := angle (p2 - p1) - angle (p1 - p0); if delta > 180: delta := delta - 360; fi; % we check for a direction change by more than % than 45 degrees if abs (delta) >= 45: do_exit := true; else: do_exit := false; fi; p0 := p1; p1 := p2; fi; % having `exitif' within an if-clause doesn't work exitif do_exit; endfor; if t >= length curve: t_good := -1; else: % the wanted point lies between `t - s' and `t' start := t - s; stop := t; t_good := start; forever: mid := 0.5 [start, stop]; exitif abs (stop - mid) <= eps; p0 := (directionpoint (direction start of curve) of object) shifted (point start of curve); p1 := (directionpoint (direction mid of curve) of object) shifted (point mid of curve); p2 := (directionpoint (direction stop of curve) of object) shifted (point stop of curve); exitif (length (p1 - p0) = 0) or (length (p2 - p1) = 0); delta := angle (p2 - p1) - angle (p1 - p0); if delta > 180: delta := delta - 360; fi; if abs (delta) >= 45: stop := mid; t_good := mid; else: start := mid; t_good := stop; fi; endfor; fi; t_good endgroup enddef; % EOF