]> git.donarmstrong.com Git - lilypond.git/blob - lily/lookup.cc
patch::: 1.1.8.hwn1
[lilypond.git] / lily / lookup.cc
1 /*
2   lookup.cc -- implement simple Lookup methods.
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--1998 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7
8   Jan Nieuwenhuizen <janneke@gnu.org>
9
10   TODO
11       Read spacing info from AFMs
12       Glissando
13 */
14
15 #include <ctype.h>
16 #include "lookup.hh"
17 #include "debug.hh"
18 #include "dimensions.hh"
19 #include "symtable.hh"
20 #include "scalar.hh"
21 #include "paper-def.hh"
22 #include "string-convert.hh"
23 #include "file-path.hh"
24 #include "main.hh"
25 #include "lily-guile.hh"
26
27
28 Lookup::Lookup ()
29 {
30   paper_l_ = 0;
31   symtables_p_ = new Symtables;
32   afm_p_ =0;
33 }
34
35 Lookup::Lookup (Lookup const& s)
36 {
37   font_ = s.font_;
38   font_path_ = s.font_path_;
39   paper_l_ = s.paper_l_;
40   symtables_p_ = new Symtables (*s.symtables_p_);
41   afm_p_ = 0;
42 }
43
44 Lookup::Lookup (Symtables const& s)
45 {
46   font_ = s.font_;
47   font_path_ = s.font_path_;
48   paper_l_ = 0;
49   symtables_p_ = new Symtables (s);
50   afm_p_ = 0;
51 }
52
53 Lookup::~Lookup ()
54 {
55   delete afm_p_;
56   delete symtables_p_;
57 }
58
59 Molecule
60 Lookup::accidental (int j, bool cautionary) const
61 {
62   Molecule m(afm_find (String ("accidentals") + String ("-") + to_str (j)));
63   if (cautionary) 
64     {
65       m.add_at_edge(X_AXIS, LEFT, 
66                     Molecule(afm_find (String ("accidentals") + String ("-("))))
67 ;
68       m.add_at_edge(X_AXIS, RIGHT, 
69                     Molecule(afm_find (String ("accidentals") + String ("-)"))))
70 ;
71     }
72   return m;
73 }
74
75 void
76 Lookup::add (String s, Symtable*p)
77 {
78   symtables_p_->add (s, p);
79 }
80
81 Atom
82 Lookup::afm_find (String s, bool warn) const
83 {
84   if (!afm_p_)
85     {
86       *mlog << "[" << font_path_;
87       ( (Lookup*)this)->afm_p_ = new Adobe_font_metric (read_afm (font_path_));
88       *mlog << "]" << flush ;
89       DOUT << this->afm_p_->str ();
90     }
91   Adobe_font_char_metric m = afm_p_->find_char (s, warn);
92
93   Atom a;
94   if (m.code () < 0)
95     return a;
96   
97   a.dim_ = m.B_;
98   a.dim_[X_AXIS] *= 1 / 1000.0;
99   a.dim_[Y_AXIS] *= 1 / 1000.0;
100   Array<Real> arr;
101   arr.push (m.code ());
102
103   
104   a.lambda_ = gh_list (ly_symbol ("char"),
105                        gh_int2scm (m.code ()),
106                        SCM_UNDEFINED);
107   a.str_ = "afm_find: " + s;
108   a.font_ = font_;
109   return a;
110 }
111
112 Atom
113 Lookup::ball (int j) const
114 {
115   if (j > 2)
116     j = 2;
117
118   return afm_find (String ("balls") + String ("-") + to_str (j));
119 }
120
121 Atom
122 Lookup::bar (String str, Real h) const
123 {
124   Array<Real> arr;
125   arr.push (h);
126   Atom a = (*symtables_p_) ("bars")->lookup (str);
127   
128   
129   a.lambda_ = gh_list (ly_symbol (a.str_.ch_C()),
130                        gh_double2scm (h),
131                        SCM_UNDEFINED);
132
133
134   a.dim_.y () = Interval (-h/2, h/2);
135   a.font_ = font_;
136   return a;
137 }
138
139 Atom 
140 Lookup::beam (Real slope, Real width, Real thick) const
141 {
142   Real height = slope * width; 
143   Real min_y = (0 <? height) - thick/2;
144   Real max_y = (0 >? height) + thick/2;
145
146   Array<Real> arr;
147   arr.push (width);
148   arr.push (slope);
149   arr.push (thick);
150
151   Atom a;
152   a.lambda_ =  (lambda_scm ("beam", arr));
153   a.str_ = "beam";
154   a.dim_[X_AXIS] = Interval (0, width);
155   a.dim_[Y_AXIS] = Interval (min_y, max_y);
156   return a;
157 }
158
159 Atom
160 Lookup::clef (String st) const
161 {
162   return afm_find (String ("clefs") + String ("-") + st);
163 }
164
165 SCM
166 offset2scm (Offset o)
167 {
168   return gh_list (gh_double2scm (o[X_AXIS]), gh_double2scm(o[Y_AXIS]),
169                   SCM_UNDEFINED);
170 }
171
172 Atom
173 Lookup::dashed_slur (Array<Offset> controls, Real thick, Real dash) const
174 {
175   assert (controls.size () == 8);
176   Offset d = controls[3] - controls[0];
177   
178   Real dx = d[X_AXIS];
179   Real dy = d[Y_AXIS];
180
181   Atom a;
182   a.font_ = font_;
183   a.dim_[X_AXIS] = Interval (0, dx);
184   a.dim_[Y_AXIS] = Interval (0 <? dy,  0 >? dy);
185
186   SCM sc[4];
187   for (int i=0; i<  4; i++)
188     {
189       sc[i] =  offset2scm (controls[i]);
190     }
191
192   // (lambda (o) (dashed-slur o thick dash '(stuff))
193   a.lambda_ = 
194     gh_list (ly_symbol ("dashed-slur"),
195              gh_double2scm (thick), 
196              gh_double2scm (dash),
197              gh_list (sc[1], sc[2], sc[3], sc[0], SCM_UNDEFINED),
198              SCM_UNDEFINED);
199
200   a.str_ = "dashed_slur";
201   return a;
202 }
203
204 Atom
205 Lookup::dots () const
206 {
207   return afm_find (String ("dots") + String ("-") + String ("dot"));
208 }
209
210 Atom
211 Lookup::dynamic (String st) const
212 {
213   return (*symtables_p_) ("dynamics")->lookup (st);
214 }
215
216 Atom
217 Lookup::extender (Real width) const
218 {
219   Atom a = (*symtables_p_) ("param")->lookup ("extender");
220   Array<Real> arr;
221   arr.push (width);
222   a.lambda_ = (lambda_scm (a.str_, arr));
223   a.str_ = "extender";
224   a.font_ = font_;
225   return a;
226 }
227
228 Atom
229 Lookup::fill (Box b) const
230 {
231   Atom a;
232   a.dim_ = b;
233   return a;
234 }
235
236 Atom
237 Lookup::flag (int j, Direction d) const
238 {
239   char c = (d == UP) ? 'u' : 'd';
240   Atom a = afm_find (String ("flags") + String ("-") + to_str (c) + to_str (j));
241   return a;
242 }
243
244 void
245 Lookup::print () const
246 {
247 #ifndef NPRINT
248   DOUT << "Lookup {\n";
249   symtables_p_->print ();
250   DOUT << "}\n";
251 #endif
252 }
253
254 Atom
255 Lookup::rest (int j, bool o) const
256 {
257    return afm_find (String ("rests")
258                     + String ("-") + to_str (j) + (o ? "o" : ""));
259 }
260
261 Atom
262 Lookup::rule_symbol (Real height, Real width) const
263 {
264   Atom a;
265   a.lambda_ = gh_list (ly_symbol ("rulesym"),
266                        gh_double2scm (height),
267                        gh_double2scm (width),
268                        SCM_UNDEFINED);
269   a.dim_.x () = Interval (0, width);
270   a.dim_.y () = Interval (0, height);
271   return a;
272 }
273
274 Atom
275 Lookup::script (String str) const
276 {
277   return afm_find (String ("scripts") + String ("-") + str);
278 }
279
280 Atom
281 Lookup::special_time_signature (String s, Array<int> arr) const
282 {
283   // First guess: s contains only the signature style
284   assert (arr.size () >1);
285   String symbolname = "timesig-" + s + to_str (arr[0]) + "/" + to_str (arr[1]);
286   
287   Atom a = afm_find (symbolname, false);
288   if (!a.empty ()) 
289     return a;
290
291   // Second guess: s contains the full signature name
292   a = afm_find ("timesig-"+s, false);
293   if (!a.empty ()) 
294     return a;
295
296   // Resort to default layout with numbers
297   return time_signature (arr);
298 }
299
300 Atom
301 Lookup::stem (Real y1, Real y2) const
302 {
303   if (y1 > y2)
304     {
305       Real t = y1;
306       y1 = y2;
307       y2 = t;
308     }
309   Atom a;
310
311   a.dim_.x () = Interval (0,0);
312   a.dim_.y () = Interval (y1,y2);
313
314   Array<Real> arr;
315
316   Real stem_width = paper_l_->get_var ("stemthickness");
317
318   gh_list (ly_symbol ("stem"),
319            gh_double2scm(-stem_width /2),
320            gh_double2scm(stem_width),
321            gh_double2scm(y2),
322            gh_double2scm(-y1),
323            SCM_UNDEFINED);
324
325   a.font_ = font_;
326   return a;
327 }
328
329 Atom
330 Lookup::streepje (int type) const
331 {
332   if (type > 2)
333     type = 2;
334
335   return  afm_find ("balls" + String ("-") +to_str (type) + "l");
336 }
337
338 Dictionary<String> cmr_dict;
339 Dictionary<Adobe_font_metric*> afm_p_dict;
340
341 Atom
342 Lookup::text (String style, String text) const
343 {
344   Array<Scalar> arr;
345
346   arr.push (text);
347   Atom a =  (*symtables_p_) ("style")->lookup (style);
348   a.lambda_ = lambda_scm (a.str_, arr);
349   Real font_w = a.dim_.x ().length ();
350   Real font_h = a.dim_.y ().length ();
351
352 // urg
353 //  if (!cmr_dict.length_i ())
354   if (!cmr_dict.elem_b ("roman"))
355     {
356       //brrrr
357       cmr_dict.elem ("bold") = "cmbx";
358       cmr_dict.elem ("dynamic") = "feta-din";
359       cmr_dict.elem ("finger") = "feta-nummer";
360       cmr_dict.elem ("italic") = "cmti";
361       cmr_dict.elem ("roman") = "cmr";
362     }
363
364   if (!afm_p_dict.elem_b (style))
365     {
366       Adobe_font_metric* afm_p = 0;
367       String cmr_str = cmr_dict.elem (style) + to_str ((int) font_h) + ".afm";
368       String font_path = global_path.find (cmr_str);
369       if (!font_path.length_i ())
370         {
371           warning (_f("can't open file: `%s'", cmr_str.ch_C ()));
372           warning (_f("guessing dimensions for font style: `%s'", style.ch_C ()));
373         }
374       else
375         {
376           *mlog << "[" << font_path;
377           afm_p = new Adobe_font_metric (read_afm (font_path));
378           DOUT << afm_p->str ();
379           *mlog << "]" << flush ;
380         }
381       afm_p_dict.elem (style) = afm_p;
382     }
383   Real w = 0;
384   Adobe_font_metric* afm_p = afm_p_dict.elem (style);
385   DOUT << "\nChars: ";
386   for (int i = 0; i < text.length_i (); i++) 
387     {
388       if (text[i]=='\\')
389         for (i++; (i < text.length_i ()) && isalpha(text[i]); i++)
390           ;
391       else
392         {
393           int c = text[i];
394           if (afm_p && ((c >= 0) && (c < afm_p->char_metrics_.size ())))
395             {
396               Adobe_font_char_metric m = afm_p->char_metrics_[c];
397               w += m.B_.x ().length ();
398               DOUT << to_str (m.B_.x ().length ()) << " ";
399             }
400           else
401               w += font_w;
402         }
403     }
404   DOUT << "\n" << to_str (w) << "\n";
405   a.dim_.x () = Interval (0, w);
406   a.str_ = "text";
407   a.font_ = font_;
408   return a;
409 }
410   
411
412 Atom
413 Lookup::time_signature (Array<int> a) const
414 {
415   Atom s ((*symtables_p_) ("param")->lookup ("time_signature"));
416   s.lambda_ =  (lambda_scm (s.str_, a));
417
418   return s;
419 }
420
421 /*
422   should be handled via Tex_ code and Lookup::bar ()
423  */
424 Atom
425 Lookup::vbrace (Real &y) const
426 {
427   Atom a = (*symtables_p_) ("param")->lookup ( "brace");
428   Interval ydims = a.dim_[Y_AXIS];
429   Real min_y = ydims[LEFT];
430   Real max_y = ydims[RIGHT];
431   Real step = 1.0 PT;
432  
433   if (y < min_y)
434     {
435       warning (_ ("piano brace") 
436                + " " + _ ("too small") +  " (" + print_dimen (y) + ")");
437       y = min_y;
438     }
439   if (y > max_y)
440     {
441       warning (_ ("piano brace")
442                + " " + _ ("too big") + " (" + print_dimen (y) + ")");
443       y = max_y;
444     }
445
446   
447   int idx = int (rint ( (y- min_y)/step)) + 1;
448   
449   Array<Real> arr;
450   arr.push (idx);
451   a.lambda_ = (lambda_scm (a.str_, arr));
452   a.str_ = "brace";
453   a.dim_[Y_AXIS] = Interval (-y/2,y/2);
454   a.font_ = font_;
455   return a;
456 }
457
458 Atom
459 Lookup::hairpin (Real width, bool decresc, bool continued) const
460 {
461   Atom a;  
462   Real height = paper_l_->staffheight_f () / 6;
463   Array<Real> arr;
464   arr.push (width);
465   arr.push (height);
466   arr.push (continued ? height/2 : 0);
467   String hairpin = String (decresc ? "de" : "") + "crescendo\n";
468   a.lambda_ = lambda_scm (hairpin, arr);
469   a.str_ = "hairpin";
470   a.dim_.x () = Interval (0, width);
471   a.dim_.y () = Interval (-2*height, 2*height);
472   a.font_ = font_;
473   return a;
474 }
475
476 Atom
477 Lookup::plet (Real dy , Real dx, Direction dir) const
478 {
479   Array<Real> arr;
480   arr.push (dx);
481   arr.push (dy);
482   arr.push (dir);
483   Atom a;
484   a.lambda_ = (lambda_scm ("tuplet", arr));
485   a.str_ = "plet";
486   return a;
487 }
488
489 SCM
490 array_to_list (SCM *a , int l)
491 {
492   SCM list = SCM_EOL;
493   for (int i= l; i--;  )
494     {
495       list =  gh_cons (a[i], list);
496     }
497   return list;
498 }
499
500 Atom
501 Lookup::slur (Array<Offset> controls) const
502 {
503   assert (controls.size () == 8);
504   Real dx = controls[3].x () - controls[0].x ();
505   Real dy = controls[3].y () - controls[0].y ();
506   Atom a;
507
508   SCM scontrols [8];
509   int indices[] = {5,6,7,4,1,2,3,0};
510
511   for (int i= 0; i < 8; i++)
512     scontrols[i] = offset2scm (controls[indices[i]]);
513
514
515   a.lambda_ =gh_list (ly_symbol ("slur"),
516                       array_to_list (scontrols, 8),
517                       SCM_UNDEFINED);
518
519   a.dim_[X_AXIS] = Interval (0, dx);
520   a.dim_[Y_AXIS] = Interval (0 <? dy,  0 >? dy);
521   a.font_ = font_;
522   return a;
523 }
524
525 Atom
526 Lookup::vbracket (Real &y) const
527 {
528   Atom a;
529   Real min_y = paper_l_->staffheight_f ();
530   if (y < min_y)
531     {
532       warning (_ ("bracket")
533                + " " + _ ("too small") +  " (" + print_dimen (y) + ")");
534       //      y = min_y;
535     }
536   Array<Real> arr;
537   arr.push (y);
538   a.lambda_ =  (lambda_scm ("bracket", arr));
539   a.str_ = "vbracket";
540   a.dim_[Y_AXIS] = Interval (-y/2,y/2);
541   a.dim_[X_AXIS] = Interval (0,4 PT);
542   return a;
543 }
544
545 Atom
546 Lookup::volta (Real w, bool last_b) const
547 {
548   Array<Real> arr;
549   arr.push (w);
550   arr.push (last_b);
551   Atom a;
552   a.lambda_ = (lambda_scm ("volta", arr));
553   a.str_ = "volta";
554   return a;
555 }
556