]> git.donarmstrong.com Git - lilypond.git/blob - lily/tex-slur.cc
cee16dbeb8c5a1df1e61baf7fd342f506c4374d3
[lilypond.git] / lily / tex-slur.cc
1 /*
2   tex-slur.cc -- implement Lookup::*slur
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1996,1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
8
9 #include <math.h>
10 #include "main.hh"
11 #include "misc.hh"
12 #include "lookup.hh"
13 #include "molecule.hh"
14 #include "dimen.hh"
15 #include "debug.hh"
16 #include "paper-def.hh"
17 #include "string-convert.hh"
18
19
20 static char
21 direction_char (Direction y_sign)
22 {
23   char c='#';
24   switch (y_sign)
25     {
26     case DOWN:
27       c = 'd';
28       break;
29     case CENTER:
30       c = 'h';
31       break;
32     case UP:
33       c = 'u';
34       break;
35     default:
36       assert (false);
37     }
38   return c;
39 }
40
41 Atom
42 Lookup::half_slur_middlepart (Real &dx, Direction dir) const
43 {
44   // todo
45   if (dx >= 400 PT)
46     {
47       WARN<<_("halfslur too large") <<print_dimen (dx)<< _("shrinking (ugh)\n");
48       dx = 400 PT;
49     }
50   int widx = int (floor (dx / 4.0));
51   dx = widx * 4.0;
52   if (widx) widx --;
53   else
54     {
55       WARN <<  _("slur too narrow\n");
56     }
57
58   Atom s;
59
60   s.dim_[Y_AXIS] = Interval (min (0, 0), max (0, 0)); // todo
61   s.dim_[X_AXIS] = Interval (-dx/2, dx/2);
62
63   String f =  String ("\\hslurchar");
64   f += direction_char (CENTER);
65
66   int idx = widx;
67   if (dir < 0)
68     idx += 128;
69
70   assert (idx < 256);
71
72   f +=String ("{") + String (idx) + "}";
73   s.tex_ = f;
74   s.translate_axis (dx/2, X_AXIS);
75
76   return s;
77 }
78
79 /*
80    The halfslurs have their center at the end pointing away from the notehead.
81    This lookup translates so that width() == [0, w]
82  */
83
84 Atom
85 Lookup::half_slur (int dy, Real &dx, Direction dir, int xpart) const
86 {
87   Real orig_dx = dx;
88   if (!xpart)
89     return half_slur_middlepart (dx, dir);
90
91   int widx;
92
93   if (dx >= 96 PT)
94     {
95       WARN << _("Slur half too wide.") << print_dimen (orig_dx) << _(" shrinking (ugh)\n");
96       dx =  96 PT;
97     }
98
99   widx = int (rint (dx/12.0));
100   dx = widx*12.0;
101   if (widx)
102     widx --;
103   else
104     {
105       WARN <<  _("slur too narrow ") << print_dimen (orig_dx)<<"\n";
106     }
107
108   Atom s;
109   s.dim_[X_AXIS] = Interval (0, dx);
110   s.dim_[Y_AXIS] = Interval (min (0, dy), max (0, dy));
111
112
113   String f = String ("\\hslurchar");
114
115   f+= direction_char (dir);
116
117   int hidx = dy;
118   if (hidx <0)
119     hidx = -hidx;
120   hidx --;
121   int idx =-1;
122
123   idx = widx * 16 + hidx;
124   if (xpart < 0)
125     idx += 128;
126
127   assert (idx < 256);
128   f+=String ("{") + String (idx) + "}";
129
130
131   s.tex_ = f;
132
133   return s;
134 }
135
136 Atom
137 Lookup::slur (int dy , Real &dx, Direction dir) const
138 {
139   assert (abs (dir) <= 1);
140   if  (dx < 0)
141     {
142       warning (_("Negative slur/tie length: ") + print_dimen (dx));
143       dx = 4.0 PT;
144     }
145
146   Atom s;
147   s.dim_[X_AXIS] = Interval (0, dx);
148   s.dim_[Y_AXIS] = Interval (min (0, dy), max (0, dy));
149
150   // duh
151   // let's try the embedded stuff
152   
153   /*  bool embedded_b = experimental_features_global_b;
154       // embedded stuff still sucks for slurs
155    */
156   bool embedded_b = false;
157   String embed;
158   if (embedded_b)
159     {
160       Real fdy = dy*paper_l_->internote_f ();
161       Real fdx = dx;
162       String ps = "\\embeddedps{\n";
163       // ugh, how bout " /draw_slur { ... } def "
164       ps += String_convert::double_str (fdx) + " " 
165         + String_convert::double_str (fdy) + " "
166         + String_convert::double_str (dir) +
167         " draw_slur}";
168
169       String mf = "\\embeddedmf{\n";
170       mf += "input feta-sleur;\n";
171       mf += "draw_slur((0,0),";
172       mf += "(" + String_convert::double_str (fdx) + "," 
173         + String_convert::double_str (fdy) + "),";
174       mf += String_convert::double_str (dir) + ");\n";
175       mf += "end.\n";
176       mf += "}\n";
177
178       embed = ps + mf;
179     }
180
181   Direction y_sign = (Direction) sign (dy);
182
183   bool large = abs (dy) > 8;
184
185   if (y_sign)
186     {
187       large |= dx>= 4*16 PT;
188     }
189   else
190     large |= dx>= 4*54 PT;
191
192   if (large)
193     {
194       s = big_slur (dy, dx, dir);
195       if (embedded_b)
196         {
197           s.tex_ = "\\embeddedtex{\n" + s.tex_ + "\n}\n";
198           s.tex_ += embed;
199         }
200       return s;
201     }
202   Real orig_dx = dx;
203   int widx = int (floor (dx/4.0)); // slurs better too small..
204   dx = 4.0 * widx;
205   if (widx)
206     widx --;
207   else
208     {
209       WARN <<  _("slur too narrow: ") << print_dimen (orig_dx) << "\n";
210     }
211
212   int hidx = dy;
213   if (hidx <0)
214     hidx = -hidx;
215   hidx --;
216   if (hidx > 8)
217     {
218       WARN<<_("slur to steep: ") << dy << _(" shrinking (ugh)\n");
219     }
220
221   String f = String ("\\slurchar") + String (direction_char (y_sign));
222
223   int idx=-1;
224   if (y_sign)
225     {
226       idx = hidx * 16 + widx;
227       if (dir < 0)
228         idx += 128;
229     }
230   else
231     {
232       if (dx >= 4*54 PT)
233         {
234           WARN << _("slur too wide: ") << print_dimen (dx) <<
235             _(" shrinking (ugh)\n");
236           dx = 4*54 PT;
237         }
238       idx = widx;
239       if (dir < 0)
240         idx += 54;
241     }
242
243   assert (idx < 256);
244   f+=String ("{") + String (idx) + "}";
245   s.tex_ = f;
246   if (embedded_b)
247     { 
248       s.tex_ = "\\embeddedtex{\n" + s.tex_ + "\n}\n";
249       s.tex_ += embed;
250     }
251
252   s.translate_axis (dx/2, X_AXIS);
253   return s;
254 }
255
256 Atom
257 Lookup::big_slur (int dy , Real &dx, Direction dir) const
258 {
259   if (dx < 24 PT)
260     {
261       warning (_("big_slur too small ") + print_dimen (dx) + _(" (stretching)"));
262       dx = 24 PT;
263     }
264
265   Real slur_extra =abs (dy)  /2.0 + 2;
266   int l_dy = int (Real (dy)/2 + slur_extra*dir);
267   int r_dy =  dy - l_dy;
268
269   Real internote_f = paper_l_->internote_f();
270   Real left_wid = dx/4.0;
271   Real right_wid = left_wid;
272
273   Atom l = half_slur (l_dy, left_wid, dir, -1);
274
275
276   Atom r = half_slur (r_dy, right_wid, dir, 1);
277   Real mid_wid = dx - left_wid - right_wid;
278
279   Molecule mol;
280   mol.add (l);
281   Atom a (half_slur (0, mid_wid, dir, 0));
282   mol.add_at_edge (X_AXIS, RIGHT, a);
283   mol.add_at_edge (X_AXIS, RIGHT, r);
284
285   mol.translate_axis (l_dy * internote_f, Y_AXIS);
286   Atom s;
287   s.tex_ = mol.TeX_string();
288   s.dim_ = mol.extent();
289   return s;
290 }