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