]> git.donarmstrong.com Git - lilypond.git/blob - lily/tex-slur.cc
release: 0.1.57
[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 #include "main.hh"
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   s.tex_ = f;
131
132   return s;
133 }
134
135 Atom
136 Lookup::ps_slur (Real dy , Real dx, Real ht, Real dir) const
137 {
138   String ps = "\\embeddedps{\n";
139   
140   ps += String_convert::double_str (dx) + " " 
141     + String_convert::double_str (dy) + " "
142     + String_convert::double_str (ht) + " "
143     + String_convert::double_str (dir) +
144     " draw_slur}";
145
146   /*
147    slurs are rarely wider than 100pt: 
148    precision of 3 yields maximum (slur spanning page)
149    error of: 1%% * 6*72pt === 0.4pt = 0.14 mm
150    */
151   String dx_str = String_convert::precision_str (dx, 4);
152   String dy_str = String_convert::precision_str (dy, 3);
153   String ht_str = String_convert::precision_str (ht, 3);
154   String dir_str = String_convert::int_str ((int)dir);
155   String name = "feta-sleur-" + dx_str + "-" + dy_str + "-" + ht_str + "-" + dir_str;
156   int i = name.index_i ('.');
157   while (i != -1)
158     {
159       *(name.ch_l () + i) = 'x';
160       i = name.index_i ('.');
161     }
162
163   String mf = "\\embeddedmf{" + name + "}{\n";
164   mf += "mode_setup;\n";
165   mf += "staffsize\\#:=" 
166     + String_convert::int_str ((int)paper_l_->get_var ("barsize"), "%d")
167     + "pt\\#;\n";
168   mf += "interline#:=staffsize#/4;\n";
169   mf += "stafflinethickness#:=0.1interline#;\n";
170   mf += "input feta-sleur;\n";
171   mf += "slurchar(" + dx_str + "," + dy_str + "," + ht_str + "," + dir_str + ");\n";
172   mf += "end.\n";
173   mf += "}\n";
174
175   Atom s;
176   s.tex_ = ps;
177   if (embedded_mf_global_b)
178     s.tex_ += mf;
179   return s;
180 }
181
182 Atom
183 Lookup::tex_slur (int dy , Real &dx, Direction dir) const
184 {
185   assert (abs ((int)dir) <= 1);
186   Atom s;
187   Direction y_sign = (Direction) sign (dy);
188
189   bool large = abs (dy) > 8;
190
191   if (y_sign)
192     {
193       large |= dx>= 4*16 PT;
194     }
195   else
196     large |= dx>= 4*54 PT;
197
198   if (large)
199     {
200       s = big_slur (dy, dx, dir);
201       return s;
202     }
203   Real orig_dx = dx;
204   int widx = int (floor (dx/4.0)); // slurs better too small..
205   dx = 4.0 * widx;
206   if (widx)
207     widx --;
208   else
209     {
210       WARN <<  _("slur too narrow: ") << print_dimen (orig_dx) << "\n";
211     }
212
213   int hidx = dy;
214   if (hidx <0)
215     hidx = -hidx;
216   hidx --;
217   if (hidx > 8)
218     {
219       WARN<<_("slur to steep: ") << dy << _(" shrinking (ugh)\n");
220     }
221
222   String f = String ("\\slurchar") + String (direction_char (y_sign));
223
224   int idx=-1;
225   if (y_sign)
226     {
227       idx = hidx * 16 + widx;
228       if (dir < 0)
229         idx += 128;
230     }
231   else
232     {
233       if (dx >= 4*54 PT)
234         {
235           WARN << _("slur too wide: ") << print_dimen (dx) <<
236             _(" shrinking (ugh)\n");
237           dx = 4*54 PT;
238         }
239       idx = widx;
240       if (dir < 0)
241         idx += 54;
242     }
243
244   assert (idx < 256);
245   f+=String ("{") + String (idx) + "}";
246   s.tex_ = f;
247   s.translate_axis (dx/2, X_AXIS);
248   return s;
249 }
250
251 Atom
252 Lookup::big_slur (int dy , Real &dx, Direction dir) const
253 {
254   if (dx < 24 PT)
255     {
256       warning (_("big_slur too small ") + print_dimen (dx) + _(" (stretching)"));
257       dx = 24 PT;
258     }
259
260   Real slur_extra =abs (dy)  /2.0 + 2;
261   int l_dy = int (Real (dy)/2 + slur_extra*dir);
262   int r_dy =  dy - l_dy;
263
264   Real internote_f = paper_l_->internote_f();
265   Real left_wid = dx/4.0;
266   Real right_wid = left_wid;
267
268   Atom l = half_slur (l_dy, left_wid, dir, -1);
269
270
271   Atom r = half_slur (r_dy, right_wid, dir, 1);
272   Real mid_wid = dx - left_wid - right_wid;
273
274   Molecule mol;
275   mol.add (l);
276   Atom a (half_slur (0, mid_wid, dir, 0));
277   mol.add_at_edge (X_AXIS, RIGHT, a);
278   mol.add_at_edge (X_AXIS, RIGHT, r);
279
280   mol.translate_axis (l_dy * internote_f, Y_AXIS);
281   Atom s;
282   s.tex_ = mol.TeX_string();
283   s.dim_ = mol.extent();
284   return s;
285 }
286
287
288 Atom
289 Lookup::slur  (Real &dy_f , Real &dx, Real ht, Direction dir) const
290 {
291   if  (dx < 0)
292     {
293       warning (_("Negative slur/tie length: ") + print_dimen (dx));
294       dx = 4.0 PT;
295     }
296   Atom s;
297   
298   if (postscript_global_b)
299     s = ps_slur (dy_f, dx, ht, dir);
300   else
301     {
302       Real nh =  paper_l_->internote_f ();
303       int dy_i = (int) rint(dy_f / nh);
304
305       s = tex_slur (dy_i, dx, dir);
306       dy_f = dy_i *  nh;
307     }
308   
309   s.dim_[X_AXIS] = Interval (0, dx);
310   s.dim_[Y_AXIS] = Interval (0 <? dy_f,  0 >? dy_f);
311   return s;
312 }
313
314 Atom
315 Lookup::control_slur (Array<Offset> controls, Real dx, Real dy) const
316 {
317   assert (postscript_global_b);
318   assert (controls.size () == 8);
319
320   String ps = "\\embeddedps{\n";
321   
322   for (int i = 1; i < 4; i++)
323     ps += String_convert::double_str (controls[i].x ()) + " "
324       + String_convert::double_str (controls[i].y ()) + " ";
325
326   for (int i = 5; i < 8; i++)
327 //    ps += String_convert::double_str (controls[i].x () + controls[0].x () - controls[3].x ()) + " "
328 //      + String_convert::double_str (controls[i].y () - controls[0].y () + controls[3].y ()) + " ";
329     ps += String_convert::double_str (controls[i].x () - dx) + " "
330       + String_convert::double_str (controls[i].y () - dy) + " ";
331
332   ps += " draw_control_slur}";
333
334   Atom s;
335   s.tex_ = ps;
336   
337   s.dim_[X_AXIS] = Interval (0, dx);
338   s.dim_[Y_AXIS] = Interval (0 <? dy,  0 >? dy);
339   return s;
340 }
341