]> git.donarmstrong.com Git - lilypond.git/blob - mf/parmesan-macros.mf
Add '-dcrop' option to ps and svg backends
[lilypond.git] / mf / parmesan-macros.mf
1 % Feta (not the Font-En-Tja) music font -- macros for parmesan font
2 % This file is part of LilyPond, the GNU music typesetter.
3 %
4 % Copyright (C) 2001--2015 Juergen Reuter <reuter@ipd.uka.de>
5
6 %
7 % The LilyPond font is free software: you can redistribute it and/or modify
8 % it under the terms of the GNU General Public License as published by
9 % the Free Software Foundation, either version 3 of the License, or
10 % (at your option) any later version, or under the SIL Open Font License.
11 %
12 % LilyPond is distributed in the hope that it will be useful,
13 % but WITHOUT ANY WARRANTY; without even the implied warranty of
14 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 % GNU General Public License for more details.
16 %
17 % You should have received a copy of the GNU General Public License
18 % along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
19
20
21 %
22 % Find point on `curve' which gives the tangent between point `p'
23 % and `curve'.  To guide the search, two auxiliary points must be
24 % specified, `p_in' and `p_out'.  The line between `p' and `p_in'
25 % must intersect `curve', while the line between `p' and `p_out'
26 % must not.
27 %
28 def find_tangent (expr p, curve, p_in, p_out) =
29         begingroup;
30         save mid, t, t_good, in, out;
31         pair mid, in, out;
32
33         in := p_in;
34         out := p_out;
35
36         forever:
37                 mid := 0.5 [in, out];
38                 exitif abs (out - mid) <= eps;
39                 t := xpart (curve intersectiontimes (p -- mid));
40                 if t > 0:
41                         in := mid;
42                         t_good := t;
43                 else:
44                         out := mid;
45                 fi;
46         endfor;
47
48         point t_good of curve
49         endgroup
50 enddef;
51
52
53 %
54 % Shift `curve' along the line given by the auxiliary points `p_in'
55 % and `p_out' until `line' is a tangent, and return the shift.
56 % If `curve' is shifted to position `p_in', it must intersect
57 % `line', while shifted to `p_out' it must not.
58 %
59 def find_tangent_shift (expr line, curve, p_in, p_out) =
60         begingroup;
61         save mid, t, in, out;
62         pair mid, in, out;
63
64         in := p_in;
65         out := p_out;
66
67         forever:
68                 mid := 0.5 [in, out];
69                 exitif abs (out - mid) <= eps;
70                 t := xpart ((curve shifted mid) intersectiontimes line);
71                 if t > 0:
72                         in := mid;
73                 else:
74                         out := mid;
75                 fi;
76         endfor;
77
78         mid
79         endgroup
80 enddef;
81
82
83 %
84 % Get subpath specified by `dir_in' and `dir_out' of `curve'
85 % which is then shifted by `offset'.  Assure that result has
86 % the same orientation as `curve'.
87 %
88 def get_subpath (expr curve, dir_in, dir_out, offset) =
89         begingroup;
90         save t_in, t_out;
91
92         t_in := directiontime dir_in of curve;
93         t_out := directiontime dir_out of curve;
94
95         if t_in > t_out:
96                 t_out := t_out + length curve;
97         fi;
98
99         (subpath (t_in, t_out) of curve) shifted offset
100         endgroup
101 enddef;
102
103
104 %
105 % Get point specified by `dir_' of `curve' which is then
106 % shifted by `offset'.
107 %
108 def get_subpoint (expr curve, dir_, offset) =
109         (directionpoint dir_ of curve) shifted offset
110 enddef;
111
112
113 %
114 % This is the same as `get_subpath', except that the time values
115 % used to construct the resulting subpath are rounded to integers.
116 %
117 def get_subpath_i (expr curve, dir_in, dir_out, offset) =
118         begingroup;
119         save t_in, t_out;
120
121         t_in := directiontime dir_in of curve;
122         t_out := directiontime dir_out of curve;
123
124         if t_in > t_out:
125                 t_out := t_out + length curve;
126         fi;
127
128         (subpath (floor (t_in + 0.5), floor (t_out + 0.5)) of curve)
129           shifted offset
130         endgroup
131 enddef;
132
133
134 %
135 % Find envelope cusp created by `object' moved along `curve', using
136 % step value `s' for initial intermediate points.  `s' must be small
137 % enough so that this macro finds at least one point on the envelope
138 % between the `entrance' and `exit' points of the cusp which has
139 % a significantly different direction vector.
140 %
141 % This function returns a time value on `curve'; if there is no
142 % cusp, it returns -1.
143 %
144 def find_envelope_cusp (expr object, curve, s) =
145         begingroup;
146         save mid, p, t, t_good, delta, start, stop, do_exit;
147         pair p[];
148         boolean do_exit;
149
150         p0 := (directionpoint (direction 0 of curve) of object)
151                 shifted (point 0 of curve);
152         p1 := (directionpoint (direction s of curve) of object)
153                 shifted (point s of curve);
154
155         t := s;
156
157         forever:
158                 t := t + s;
159                 exitif t >= length curve;
160
161                 p2 := (directionpoint (direction t of curve) of object)
162                         shifted (point t of curve);
163                 if p2 <> p1:
164                         delta := angle (p2 - p1) - angle (p1 - p0);
165                         if delta > 180:
166                                 delta := delta - 360;
167                         fi;
168
169                         % we check for a direction change by more than
170                         % than 45 degrees
171                         if abs (delta) >= 45:
172                                 do_exit := true;
173                         else:
174                                 do_exit := false;
175                         fi;
176
177                         p0 := p1;
178                         p1 := p2;
179                 fi;
180
181                 % having `exitif' within an if-clause doesn't work
182                 exitif do_exit;
183         endfor;
184
185         if t >= length curve:
186                 t_good := -1;
187         else:
188                 % the wanted point lies between `t - s' and `t'
189                 start := t - s;
190                 stop := t;
191                 t_good := start;
192
193                 forever:
194                         mid := 0.5 [start, stop];
195                         exitif abs (stop - mid) <= eps;
196
197                         p0 := (directionpoint (direction start of curve)
198                                 of object) shifted (point start of curve);
199                         p1 := (directionpoint (direction mid of curve)
200                                 of object) shifted (point mid of curve);
201                         p2 := (directionpoint (direction stop of curve)
202                                 of object) shifted (point stop of curve);
203
204                         exitif (length (p1 - p0) = 0)
205                                 or (length (p2 - p1) = 0);
206
207                         delta := angle (p2 - p1) - angle (p1 - p0);
208                         if delta > 180:
209                                 delta := delta - 360;
210                         fi;
211
212                         if abs (delta) >= 45:
213                                 stop := mid;
214                                 t_good := mid;
215                         else:
216                                 start := mid;
217                                 t_good := stop;
218                         fi;
219                 endfor;
220         fi;
221
222         t_good
223         endgroup
224 enddef;
225
226 % EOF