]> git.donarmstrong.com Git - lilypond.git/blob - lily/lookup.cc
release: 1.1.26
[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   Real h = 0;
414   Real d = 0;
415
416   Font_metric* afm_l = all_fonts_global_p->find_font (style);
417   DOUT << "\nChars: ";
418   
419   for (int i = 0; i < text.length_i (); i++) 
420     {
421       if (text[i]=='\\')
422         for (i++; (i < text.length_i ()) && isalpha(text[i]); i++)
423           ;
424       else
425         {
426           Character_metric *c = afm_l->get_char (text[i],false);
427           w += c->dimensions()[X_AXIS].length ();
428           h = h >? c->dimensions()[Y_AXIS].max ();
429           d = d <? c->dimensions()[Y_AXIS].min ();
430         }
431     }
432
433   DOUT << "\n" << to_str (w) << "\n";
434   a.dim_.x () = Interval (0, w);
435   a.dim_.y () = Interval (d, h);
436   a.font_ = font_name_;
437   return a;
438 }
439   
440
441 /*
442   TODO: should return a molecule with 2 stacked nums.
443  */
444 Atom
445 Lookup::time_signature (Array<int> a) const
446 {
447   Atom s;
448   s.lambda_ = gh_list (ly_symbol ("generalmeter"),
449                        gh_int2scm (a[0]),
450                        gh_int2scm (a[1]),
451                        SCM_UNDEFINED);
452
453   Real r = paper_l_->interline_f () ;
454   s.dim_[Y_AXIS] =  Interval (-2*r, 2*r);
455   s.dim_[X_AXIS] = Interval (0, 2*r);
456   return s;
457 }
458
459 Atom
460 Lookup::vbrace (Real &y) const
461 {
462   Atom a;
463   a.lambda_ = gh_list (ly_symbol ("pianobrace"),
464                        gh_double2scm (y),
465                        SCM_UNDEFINED
466                        );
467   a.dim_[Y_AXIS] = Interval (-y/2,y/2);
468   a.dim_[X_AXIS] = Interval (0,0);
469   a.font_ = font_name_;
470   return a;
471 }
472
473 Atom
474 Lookup::hairpin (Real width, bool decresc, bool continued) const
475 {
476   Atom a;  
477   Real height = paper_l_->staffheight_f () / 6;
478
479   String hairpin = String (decresc ? "de" : "") + "crescendo";
480   a.lambda_ = gh_list (ly_symbol (hairpin),
481                        gh_double2scm (width),
482                        gh_double2scm (height),
483                        gh_double2scm (continued ? height/2 : 0.0),
484                        SCM_UNDEFINED);
485   a.dim_.x () = Interval (0, width);
486   a.dim_.y () = Interval (-2*height, 2*height);
487   a.font_ = font_name_;
488   return a;
489 }
490
491 Atom
492 Lookup::plet (Real dy , Real dx, Direction dir) const
493 {
494   Atom a;
495   SCM thick = ly_symbol ("tuplet_thick");
496   Real t = 0.1 PT;
497   if (paper_l_->scope_p_->elem_b (thick))
498     {
499       t = paper_l_->get_realvar (thick);
500     }
501   a.lambda_ = gh_list(ly_symbol ("tuplet"),
502                       gh_double2scm (dx),
503                       gh_double2scm (dy),
504                       gh_double2scm (t),
505                       gh_int2scm (dir),
506                       SCM_UNDEFINED);
507   return a;
508 }
509
510
511 Atom
512 Lookup::slur (Array<Offset> controls) const
513 {
514   assert (controls.size () == 8);
515   Real dx = controls[3].x () - controls[0].x ();
516   Real dy = controls[3].y () - controls[0].y ();
517   Atom a;
518
519   SCM scontrols [8];
520   int indices[] = {5,6,7,4,1,2,3,0};
521
522   for (int i= 0; i < 8; i++)
523     scontrols[i] = offset2scm (controls[indices[i]]);
524
525
526   a.lambda_ =gh_list (ly_symbol ("slur"),
527                       ly_quote_scm (array_to_list (scontrols, 8)),
528                       SCM_UNDEFINED);
529
530   a.dim_[X_AXIS] = Interval (0, dx);
531   a.dim_[Y_AXIS] = Interval (0 <? dy,  0 >? dy);
532   a.font_ = font_name_;
533   return a;
534 }
535
536 Atom
537 Lookup::vbracket (Real &y) const
538 {
539   Atom a;
540   a.lambda_ =  gh_list (ly_symbol ("bracket"),
541                         gh_double2scm (y),
542                         SCM_UNDEFINED);
543   a.dim_[Y_AXIS] = Interval (-y/2,y/2);
544   a.dim_[X_AXIS] = Interval (0,4 PT);
545   return a;
546 }
547
548 Atom
549 Lookup::volta (Real w, bool last_b) const
550 {
551   Atom a;
552   SCM thick = ly_symbol ("volta_thick");
553   Real t = 0.1 PT;
554   if (paper_l_->scope_p_->elem_b (thick))
555     {
556       t = paper_l_->get_realvar (thick);
557     }
558   a.lambda_ = gh_list (ly_symbol ("volta"),
559                        gh_double2scm (w),
560                        gh_double2scm (t),
561                        gh_int2scm (last_b),
562                        SCM_UNDEFINED);
563
564   Real interline_f = paper_l_->interline_f ();
565
566   a.dim_[Y_AXIS] = Interval (-interline_f, interline_f);
567   a.dim_[X_AXIS] = Interval (0, w);
568   return a;
569 }
570
571
572 Atom
573 Lookup::special_ball (int j, String kind_of_ball) const
574 {
575   if (j > 2)
576     j = 2;
577
578   return afm_find (String ("balls") + String ("-") + kind_of_ball);
579 }