]> git.donarmstrong.com Git - lilypond.git/blob - lily/slur.cc
release: 0.0.40
[lilypond.git] / lily / slur.cc
1 /*
2
3   TODO:
4   think about crossing stems.
5  */
6 #include "slur.hh"
7 #include "scalar.hh"
8 #include "lookup.hh"
9 #include "paper-def.hh"
10 #include "notehead.hh"
11 #include "pcol.hh"
12 #include "molecule.hh"
13 #include "debug.hh"
14 #include "boxes.hh"
15
16
17
18 Slur::Slur()
19 {
20     open_right=open_left=false;
21 }
22
23 Offset
24 Slur::center() const
25 {
26     int pos1 = encompass.top()->position;
27     int pos2 = encompass[0]->position;
28
29     int dy =  pos1-pos2;
30
31     Real w = width().length();
32
33     return Offset(w/2,dy * paper()->internote());
34 }
35
36 void
37 Slur::add(Notehead*n)
38 {
39     encompass.push(n);
40     add_dependency(n);
41 }
42
43 void
44 Slur::set_default_dir()
45 {
46     int sumpos=0;
47     for (int i=0; i < encompass.size(); i ++) {
48         sumpos += encompass[i]->position;
49     }
50
51     /* should consult stems */
52     Real meanpos = sumpos/Real(encompass.size());
53     if (meanpos < 5)            // todo
54         dir_i_ = -1;
55     else
56         dir_i_ = 1;    
57 }
58
59 void
60 Slur::do_pre_processing()
61 {
62     right  = encompass.top()->pcol_l_;
63     left = encompass[0]->pcol_l_;    
64 }
65
66 Spanner*
67 Slur::do_break_at(PCol*l, PCol*r) const
68 {
69     assert(l->line_l_ == r->line_l_);
70     Slur*ret = new Slur(*this);
71
72     ret->encompass.set_size(0);
73     for (int i =0; i < encompass.size(); i++) {
74         if (encompass[i]->pcol_l_->line_l_==l->line_l_)
75             ret->encompass.push(encompass[i]);
76     }
77     if (right != r)
78         ret->open_right = true;
79     if (left != l)
80         ret->open_left = true;
81
82
83     return ret;
84 }
85
86 void
87 Slur::do_post_processing()
88 {
89     if (!dir_i_)
90         set_default_dir();
91 }
92
93 Molecule*
94 Slur::brew_molecule_p() const
95 {
96     Molecule*output = new Molecule;
97
98     int minp=1000, maxp=-1000;  // todo    
99     for (int i=0; i<encompass.size(); i++) {
100         minp = encompass[i]->position <? minp;
101         maxp = encompass[i]->position >? maxp;
102     }
103     assert(encompass.size()>0); // todo
104     
105     Notehead *lnote_p =encompass[0];
106     Notehead *rnote_p =encompass.top();
107     int lpos_i = lnote_p->position;
108     int rpos_i = rnote_p->position;
109     Offset  left_off(lnote_p->x_dir, lpos_i + 2*dir_i_);
110     Offset right_off(lnote_p->x_dir, rpos_i + 2*dir_i_);
111     if (!lnote_p->extremal)
112         left_off += Offset(0.5, -dir_i_);
113     if (!rnote_p->extremal)
114         right_off+= Offset(-0.5, -dir_i_);
115     
116     int dy = int(right_off.y - left_off.y);
117     
118     Real nw_f = paper()->note_width();
119     Real nh_f = paper()->internote();
120     Real w = width().length();
121     
122     w+= (right_off.x - left_off.x) * nw_f ;
123     Real round_w = w;           // slur lookup rounds the slurwidth .
124     
125     Symbol sl = paper()->lookup_l()->slur(dy , round_w, dir_i_);
126
127     Real error = w-round_w;
128     
129     Atom a(sl);
130     a.translate(Offset((left_off.x + 0.5 )*nw_f + error/2,
131                        left_off.y * nh_f));
132     output->add(a);
133     return output;
134 }
135