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