lilypond-1.3.16
[lilypond.git] / lily / tex-slur.cc
blobab86f271fa9c8f7e2b571d26e2e3ca3f90d807ef
1 /*
2 tex-slur.cc -- implement Lookup::*slur
4 source file of the GNU LilyPond music typesetter
6 (c) 1996,1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
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"
20 static char
21 direction_char (Direction y_sign)
23 char c='#';
24 switch (y_sign)
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);
38 return c;
41 Atom
42 Lookup::half_slur_middlepart (Real &dx, Direction dir) const
44 // todo
45 if (dx >= 400 PT)
47 WARN<<_("halfslur too large") <<print_dimen (dx)<< _("shrinking (ugh)\n");
48 dx = 400 PT;
50 int widx = int (floor (dx / 4.0));
51 dx = widx * 4.0;
52 if (widx) widx --;
53 else
55 WARN << _("slur too narrow\n");
58 Atom s;
60 s.dim_[Y_AXIS] = Interval (min (0, 0), max (0, 0)); // todo
61 s.dim_[X_AXIS] = Interval (-dx/2, dx/2);
63 String f = String ("\\hslurchar");
64 f += direction_char (CENTER);
66 int idx = widx;
67 if (dir < 0)
68 idx += 128;
70 assert (idx < 256);
72 f +=String ("{") + String (idx) + "}";
73 s.tex_ = f;
74 s.translate_axis (dx/2, X_AXIS);
76 return s;
80 The halfslurs have their center at the end pointing away from the notehead.
81 This lookup translates so that width() == [0, w]
84 Atom
85 Lookup::half_slur (int dy, Real &dx, Direction dir, int xpart) const
87 Real orig_dx = dx;
88 if (!xpart)
89 return half_slur_middlepart (dx, dir);
91 int widx;
93 if (dx >= 96 PT)
95 WARN << _("Slur half too wide.") << print_dimen (orig_dx) << _(" shrinking (ugh)\n");
96 dx = 96 PT;
99 widx = int (rint (dx/12.0));
100 dx = widx*12.0;
101 if (widx)
102 widx --;
103 else
105 WARN << _("slur too narrow ") << print_dimen (orig_dx)<<"\n";
108 Atom s;
109 s.dim_[X_AXIS] = Interval (0, dx);
110 s.dim_[Y_AXIS] = Interval (min (0, dy), max (0, dy));
113 String f = String ("\\hslurchar");
115 f+= direction_char (dir);
117 int hidx = dy;
118 if (hidx <0)
119 hidx = -hidx;
120 hidx --;
121 int idx =-1;
123 idx = widx * 16 + hidx;
124 if (xpart < 0)
125 idx += 128;
127 assert (idx < 256);
128 f+=String ("{") + String (idx) + "}";
130 s.tex_ = f;
132 return s;
135 Atom
136 Lookup::ps_slur (Real dy , Real dx, Real ht, Real dir) const
138 String ps = "\\embeddedps{\n";
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}";
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
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)
159 *(name.ch_l () + i) = 'x';
160 i = name.index_i ('.');
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";
175 Atom s;
176 s.tex_ = ps;
177 if (embedded_mf_global_b)
178 s.tex_ += mf;
179 return s;
182 Atom
183 Lookup::tex_slur (int dy , Real &dx, Direction dir) const
185 assert (abs ((int)dir) <= 1);
186 Atom s;
187 Direction y_sign = (Direction) sign (dy);
189 bool large = abs (dy) > 8;
191 if (y_sign)
193 large |= dx>= 4*16 PT;
195 else
196 large |= dx>= 4*54 PT;
198 if (large)
200 s = big_slur (dy, dx, dir);
201 return s;
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
210 WARN << _("slur too narrow: ") << print_dimen (orig_dx) << "\n";
213 int hidx = dy;
214 if (hidx <0)
215 hidx = -hidx;
216 hidx --;
217 if (hidx > 8)
219 WARN<<_("slur to steep: ") << dy << _(" shrinking (ugh)\n");
222 String f = String ("\\slurchar") + String (direction_char (y_sign));
224 int idx=-1;
225 if (y_sign)
227 idx = hidx * 16 + widx;
228 if (dir < 0)
229 idx += 128;
231 else
233 if (dx >= 4*54 PT)
235 WARN << _("slur too wide: ") << print_dimen (dx) <<
236 _(" shrinking (ugh)\n");
237 dx = 4*54 PT;
239 idx = widx;
240 if (dir < 0)
241 idx += 54;
244 assert (idx < 256);
245 f+=String ("{") + String (idx) + "}";
246 s.tex_ = f;
247 s.translate_axis (dx/2, X_AXIS);
248 return s;
251 Atom
252 Lookup::big_slur (int dy , Real &dx, Direction dir) const
254 if (dx < 24 PT)
256 warning (_("big_slur too small ") + print_dimen (dx) + _(" (stretching)"));
257 dx = 24 PT;
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;
264 Real internote_f = paper_l_->internote_f();
265 Real left_wid = dx/4.0;
266 Real right_wid = left_wid;
268 Atom l = half_slur (l_dy, left_wid, dir, -1);
271 Atom r = half_slur (r_dy, right_wid, dir, 1);
272 Real mid_wid = dx - left_wid - right_wid;
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);
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;
288 Atom
289 Lookup::slur (Real &dy_f , Real &dx, Real ht, Direction dir) const
291 if (dx < 0)
293 warning (_("Negative slur/tie length: ") + print_dimen (dx));
294 dx = 4.0 PT;
296 Atom s;
298 if (postscript_global_b)
299 s = ps_slur (dy_f, dx, ht, dir);
300 else
302 Real nh = paper_l_->internote_f ();
303 int dy_i = (int) rint(dy_f / nh);
305 s = tex_slur (dy_i, dx, dir);
306 dy_f = dy_i * nh;
309 s.dim_[X_AXIS] = Interval (0, dx);
310 s.dim_[Y_AXIS] = Interval (0 <? dy_f, 0 >? dy_f);
311 return s;
314 Atom
315 Lookup::control_slur (Array<Offset> controls, Real dx, Real dy) const
317 assert (postscript_global_b);
318 assert (controls.size () == 8);
320 String ps = "\\embeddedps{\n";
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 ()) + " ";
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) + " ";
332 ps += " draw_control_slur}";
334 Atom s;
335 s.tex_ = ps;
337 s.dim_[X_AXIS] = Interval (0, dx);
338 s.dim_[Y_AXIS] = Interval (0 <? dy, 0 >? dy);
339 return s;