]> git.donarmstrong.com Git - lilypond.git/blob - lily/lookup.cc
release: 1.3.93
[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--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7
8   Jan Nieuwenhuizen <janneke@gnu.org>
9
10   TODO
11       Glissando
12 */
13 #include <math.h>
14 #include <ctype.h>
15
16 #include "lookup.hh"
17 #include "warn.hh"
18 #include "dimensions.hh"
19 #include "bezier.hh"
20 #include "paper-def.hh"
21 #include "string-convert.hh"
22 #include "file-path.hh"
23 #include "main.hh"
24 #include "lily-guile.hh"
25 #include "all-font-metrics.hh"
26 #include "afm.hh"
27 #include "scope.hh"
28 #include "molecule.hh"
29
30
31 #include "ly-smobs.icc"
32
33
34 Lookup::Lookup ()
35 {
36   afm_l_ = 0;  
37 }
38
39 Lookup::Lookup (Lookup const& s)
40 {
41   font_name_ = s.font_name_;
42   afm_l_ = 0;
43 }
44
45 SCM
46 Lookup::mark_smob (SCM s)
47 {
48   return s;  
49 }
50
51 int
52 Lookup::print_smob (SCM s, SCM p, scm_print_state*)
53 {
54   scm_puts ("#<Lookup >#", p);
55   return 1;
56 }
57
58
59 IMPLEMENT_UNSMOB(Lookup, lookup);
60 IMPLEMENT_SIMPLE_SMOBS(Lookup);
61 IMPLEMENT_DEFAULT_EQUAL_P(Lookup);
62
63 SCM
64 Lookup::make_lookup ()
65 {
66   Lookup * l = new Lookup;
67   return l->smobbed_self();
68 }
69
70
71 Molecule
72 Lookup::afm_find (String s, bool warn) const
73 {
74   if (!afm_l_)      
75     {
76       Lookup * me = (Lookup*)(this);
77       me->afm_l_ = all_fonts_global_p->find_afm (font_name_);
78       if (!me->afm_l_)
79         {
80           warning (_f ("can't find font: `%s'", font_name_));
81           warning (_f ("(search path: `%s')", global_path.str ().ch_C()));
82           error (_ ("Aborting"));
83         }
84     }
85   AFM_CharMetricInfo const *cm = afm_l_->find_char_metric (s, warn);
86
87   if (!cm)
88     {
89       Molecule m;
90       m.set_empty (false);
91       return m;
92     }
93   
94   SCM at =  (gh_list (ly_symbol2scm ("char"),
95                     gh_int2scm (cm->code),
96                     SCM_UNDEFINED));
97
98
99   at= fontify_atom (afm_l_,at);
100   return Molecule ( afm_bbox_to_box (cm->charBBox), at);
101 }
102
103   
104
105
106 Molecule 
107 Lookup::beam (Real slope, Real width, Real thick) 
108 {
109   Real height = slope * width; 
110   Real min_y = (0 <? height) - thick/2;
111   Real max_y = (0 >? height) + thick/2;
112
113   
114
115   Box b( Interval (0, width),
116          Interval (min_y, max_y));
117
118   
119   SCM at = gh_list (ly_symbol2scm ("beam"),
120                     gh_double2scm (width),
121                     gh_double2scm (slope),
122                     gh_double2scm (thick),
123                     SCM_UNDEFINED);
124   return Molecule (b, at);
125 }
126
127
128
129 Molecule
130 Lookup::dashed_slur (Bezier b, Real thick, Real dash)
131 {
132   SCM l = SCM_EOL;
133
134   for (int i= 4; i -- ;)
135     {
136       l = gh_cons (ly_offset2scm (b.control_[i]), l);
137     }
138
139   SCM at = (gh_list (ly_symbol2scm ("dashed-slur"),
140                                gh_double2scm (thick), 
141                                gh_double2scm (dash),
142                                ly_quote_scm (l),
143                                SCM_UNDEFINED));
144
145   Box box (Interval(0,0),Interval( 0,0));
146   return   Molecule (box, at);
147 }
148
149
150
151
152 Molecule
153 Lookup::blank (Box b) 
154 {
155   return Molecule (b, SCM_EOL);
156 }
157
158
159 Molecule
160 Lookup::filledbox (Box b ) 
161 {
162   SCM  at  = (gh_list (ly_symbol2scm ("filledbox"),
163                      gh_double2scm (-b[X_AXIS][LEFT]),
164                      gh_double2scm (b[X_AXIS][RIGHT]),                 
165                      gh_double2scm (-b[Y_AXIS][DOWN]),
166                      gh_double2scm (b[Y_AXIS][UP]),                    
167                      SCM_UNDEFINED));
168
169   return Molecule ( b,at);
170 }
171
172 Molecule
173 Lookup::frame (Box b, Real thick)
174 {
175   Molecule m;
176   Direction d = LEFT;
177   Axis a = X_AXIS;
178   while (a < NO_AXES)
179     {
180       do
181         {
182           Axis o = Axis ((a+1)%NO_AXES);
183
184           Box edges;
185           edges[a] = b[a][d] + 0.5 * thick * Interval (-1, 1);
186           edges[o][DOWN] = b[o][DOWN] - thick/2;
187           edges[o][UP] = b[o][UP] + thick/2;      
188           
189           
190           m.add_molecule (filledbox (edges));
191         }
192       while (flip (&d) != LEFT);
193     }
194   return m;
195   
196 }
197
198
199 /*
200    TODO: THIS IS UGLY.
201    Since the user has direct access to TeX marcos,
202    that currently provide the  only way to do
203    font selection, accents etc,
204    we try some halfbaked attempt to detect this TeX trickery.
205  */
206 String
207 sanitise_TeX_string (String text)
208 {
209   int brace_count =0;
210   for (int i= 0; i < text.length_i (); i++)
211     {
212       if (text[i] == '\\')
213         continue;
214       
215       if (text[i] == '{')
216         brace_count ++;
217       else if (text[i] == '}')
218         brace_count --;
219     }
220   
221   if(brace_count)
222     {
223       warning (_f ("Non-matching braces in text `%s', adding braces", text.ch_C()));
224
225       if (brace_count < 0)
226         {
227           text = to_str ('{', -brace_count) + text;
228         }
229       else 
230         {
231           text = text + to_str ('}', brace_count);
232         }
233     }
234     
235   return text;
236 }
237
238 /**
239    TODO!
240  */
241 String
242 sanitise_PS_string (String t)
243 {
244   return t;
245 }
246
247 /**
248 TODO: move into Text_item. UGH: paper_l argument shoudl be junked.
249 */
250 Molecule
251 Lookup::text (String style, String text, Paper_def *paper_l) 
252 {
253   if (style.empty_b ())
254     style = "roman";
255   
256   int font_mag = 0;
257   Real font_h = paper_l->get_var ("font_normal");
258   if (paper_l->scope_p_->elem_b ("font_" + style))
259     {
260       font_h = paper_l->get_var ("font_" + style);
261     }
262
263
264   if (paper_l->scope_p_->elem_b ("magnification_" + style))
265     {
266       font_mag = (int)paper_l->get_var ("magnification_" + style);
267     }
268
269   /*
270     FIXME !
271    */
272   
273   SCM l = scm_assoc (ly_str02scm (style.ch_C()),
274                      scm_eval2 (ly_symbol2scm ("cmr-alist"), SCM_EOL));
275
276   if (l != SCM_BOOL_F)
277     {
278       style = ly_scm2string (gh_cdr(l)) +to_str  ((int)font_h);
279     }
280
281   Font_metric* metric_l = 0;
282
283   if (font_mag)
284     metric_l = all_fonts_global_p->find_scaled (style, font_mag);
285   else
286     metric_l = all_fonts_global_p->find_font (style);
287   
288   
289     
290
291   int i = text.index_i ("\\n");
292   while (i >=0 )
293     {
294       text = text.left_str (i) + "\n" + text.right_str (text.length_i () - i - 2);
295       i = text.index_i ("\\n");
296     }
297   
298   Array<String> lines = String_convert::split_arr (text, '\n');
299   
300   Real kern = paper_l->get_var ("line_kern");
301   
302   for (int i=0; i < lines.size (); i++)
303     {
304       String str (lines[i]);
305       if (output_global_ch == "tex")
306         str = sanitise_TeX_string  (str);
307       else if (output_global_ch == "ps")
308         str = sanitise_PS_string (str);
309       lines[i] = str;
310     }
311
312   if (!lines.size())
313         return Molecule();
314
315   SCM first = gh_list (ly_symbol2scm ("text"),
316                          ly_str02scm (lines[0].ch_C()),
317                          SCM_UNDEFINED);
318   first = fontify_atom (metric_l, first);
319
320   
321
322   Molecule mol (metric_l->text_dimension (lines[0]), first);
323
324   for (i = 1; i < lines.size (); i++)
325     {
326       SCM line = (gh_list (ly_symbol2scm ("text"),
327                            ly_str02scm (lines[i].ch_C ()),
328                            SCM_UNDEFINED));
329       line = fontify_atom (metric_l, line);
330       mol.add_at_edge (Y_AXIS, DOWN,
331                        Molecule (metric_l->text_dimension (lines[i]), line),
332                        kern);
333     }
334
335   return mol;
336 }
337   
338
339
340 /*
341   Make a smooth curve along the points 
342  */
343 Molecule
344 Lookup::slur (Bezier curve, Real curvethick, Real linethick) 
345 {
346   Real alpha = (curve.control_[3] - curve.control_[0]).arg ();
347   Bezier back = curve;
348
349   back.reverse ();
350   back.control_[1] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
351   back.control_[2] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));  
352
353   SCM scontrols[8];
354
355   for (int i=4; i--;)
356     scontrols[ i ] = ly_offset2scm(back.control_[i]);
357   for (int i=4 ; i--;)
358     scontrols[i+4] = ly_offset2scm (curve.control_[i]);
359
360   /*
361     Need the weird order b.o. the way PS want its arguments  
362    */
363   int indices[]= {5, 6, 7, 4, 1, 2, 3, 0};
364   SCM list = SCM_EOL;
365   for (int i= 8; i--;  )
366     {
367       list = gh_cons (scontrols[indices[i]], list);
368     }
369   
370   
371   SCM at = (gh_list (ly_symbol2scm ("bezier-sandwich"),
372                      ly_quote_scm (list),
373                      gh_double2scm (linethick),
374                      SCM_UNDEFINED));
375
376   Box b ( curve.extent (X_AXIS), curve.extent (Y_AXIS));
377   return Molecule (b, at);
378 }
379
380 Molecule
381 Lookup::accordion (SCM s, Real staff_space) const
382 {
383   Molecule m;
384   String sym = ly_scm2string(gh_car (s));
385   String reg = ly_scm2string(gh_car (gh_cdr(s)));
386
387   if (sym == "Discant")
388     {
389       Molecule r = afm_find("accordion-accDiscant");
390       m.add_molecule(r);
391       if (reg.left_str(1) == "F")
392         {
393           Molecule d = afm_find("accordion-accDot");
394           d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
395           m.add_molecule(d);
396           reg = reg.right_str(reg.length_i()-1);
397         }
398       int eflag = 0x00;
399       if (reg.left_str(3) == "EEE")
400         {
401           eflag = 0x07;
402           reg = reg.right_str(reg.length_i()-3);
403         }
404       else if (reg.left_str(2) == "EE")
405         {
406           eflag = 0x05;
407           reg = reg.right_str(reg.length_i()-2);
408         }
409       else if (reg.left_str(2) == "Eh")
410         {
411           eflag = 0x04;
412           reg = reg.right_str(reg.length_i()-2);
413         }
414       else if (reg.left_str(1) == "E")
415         {
416           eflag = 0x02;
417           reg = reg.right_str(reg.length_i()-1);
418         }
419       if (eflag & 0x02)
420         {
421           Molecule d = afm_find("accordion-accDot");
422           d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
423           m.add_molecule(d);
424         }
425       if (eflag & 0x04)
426         {
427           Molecule d = afm_find("accordion-accDot");
428           d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
429           d.translate_axis(0.8 * staff_space PT, X_AXIS);
430           m.add_molecule(d);
431         }
432       if (eflag & 0x01)
433         {
434           Molecule d = afm_find("accordion-accDot");
435           d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
436           d.translate_axis(-0.8 * staff_space PT, X_AXIS);
437           m.add_molecule(d);
438         }
439       if (reg.left_str(2) == "SS")
440         {
441           Molecule d = afm_find("accordion-accDot");
442           d.translate_axis(0.5 * staff_space PT, Y_AXIS);
443           d.translate_axis(0.4 * staff_space PT, X_AXIS);
444           m.add_molecule(d);
445           d.translate_axis(-0.8 * staff_space PT, X_AXIS);
446           m.add_molecule(d);
447           reg = reg.right_str(reg.length_i()-2);
448         }
449       if (reg.left_str(1) == "S")
450         {
451           Molecule d = afm_find("accordion-accDot");
452           d.translate_axis(0.5 * staff_space PT, Y_AXIS);
453           m.add_molecule(d);
454           reg = reg.right_str(reg.length_i()-1);
455         }
456     }
457   else if (sym == "Freebase")
458     {
459       Molecule r = afm_find("accordion-accFreebase");
460       m.add_molecule(r);
461       if (reg.left_str(1) == "F")
462         {
463           Molecule d = afm_find("accordion-accDot");
464           d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
465           m.add_molecule(d);
466           reg = reg.right_str(reg.length_i()-1);
467         }
468       if (reg == "E")
469         {
470           Molecule d = afm_find("accordion-accDot");
471           d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
472           m.add_molecule(d);
473         }
474     }
475   else if (sym == "Bayanbase")
476     {
477       Molecule r = afm_find("accordion-accBayanbase");
478       m.add_molecule(r);
479       if (reg.left_str(1) == "T")
480         {
481           Molecule d = afm_find("accordion-accDot");
482           d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
483           m.add_molecule(d);
484           reg = reg.right_str(reg.length_i()-1);
485         }
486       /* include 4' reed just for completeness. You don't want to use this. */
487       if (reg.left_str(1) == "F")
488         {
489           Molecule d = afm_find("accordion-accDot");
490           d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
491           m.add_molecule(d);
492           reg = reg.right_str(reg.length_i()-1);
493         }
494       if (reg.left_str(2) == "EE")
495         {
496           Molecule d = afm_find("accordion-accDot");
497           d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
498           d.translate_axis(0.4 * staff_space PT, X_AXIS);
499           m.add_molecule(d);
500           d.translate_axis(-0.8 * staff_space PT, X_AXIS);
501           m.add_molecule(d);
502           reg = reg.right_str(reg.length_i()-2);
503         }
504       if (reg.left_str(1) == "E")
505         {
506           Molecule d = afm_find("accordion-accDot");
507           d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
508           m.add_molecule(d);
509           reg = reg.right_str(reg.length_i()-1);
510         }
511     }
512   else if (sym == "Stdbase")
513     {
514       Molecule r = afm_find("accordion-accStdbase");
515       m.add_molecule(r);
516       if (reg.left_str(1) == "T")
517         {
518           Molecule d = afm_find("accordion-accDot");
519           d.translate_axis(staff_space * 3.5 PT, Y_AXIS);
520           m.add_molecule(d);
521           reg = reg.right_str(reg.length_i()-1);
522         }
523       if (reg.left_str(1) == "F")
524         {
525           Molecule d = afm_find("accordion-accDot");
526           d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
527           m.add_molecule(d);
528           reg = reg.right_str(reg.length_i()-1);
529         }
530       if (reg.left_str(1) == "M")
531         {
532           Molecule d = afm_find("accordion-accDot");
533           d.translate_axis(staff_space * 2 PT, Y_AXIS);
534           d.translate_axis(staff_space PT, X_AXIS);
535           m.add_molecule(d);
536           reg = reg.right_str(reg.length_i()-1);
537         }
538       if (reg.left_str(1) == "E")
539         {
540           Molecule d = afm_find("accordion-accDot");
541           d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
542           m.add_molecule(d);
543           reg = reg.right_str(reg.length_i()-1);
544         }
545       if (reg.left_str(1) == "S")
546         {
547           Molecule d = afm_find("accordion-accDot");
548           d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
549           m.add_molecule(d);
550           reg = reg.right_str(reg.length_i()-1);
551         }
552     }
553   /* ugh maybe try to use regular font for S.B. and B.B and only use one font
554      for the rectangle */
555   else if (sym == "SB")
556     {
557       Molecule r = afm_find("accordion-accSB");
558       m.add_molecule(r);
559     }
560   else if (sym == "BB")
561     {
562       Molecule r = afm_find("accordion-accBB");
563       m.add_molecule(r);
564     }
565   else if (sym == "OldEE")
566     {
567       Molecule r = afm_find("accordion-accOldEE");
568       m.add_molecule(r);
569     }
570   else if (sym == "OldEES")
571     {
572       Molecule r = afm_find("accordion-accOldEES");
573       m.add_molecule(r);
574     }
575   return m;  
576 }
577