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