]> git.donarmstrong.com Git - lilypond.git/blob - src/stem.cc
release: 0.0.9
[lilypond.git] / src / stem.cc
1 #include "stem.hh"
2 #include "dimen.hh" 
3 #include "debug.hh"
4 #include "paper.hh"
5 #include "notehead.hh"
6 #include "lookup.hh"
7 #include "molecule.hh"
8 #include "pcol.hh"
9
10 const int STEMLEN=7;
11 static int
12 ABS(int i) {
13     return (i < 0)?-i:i;
14 }
15
16
17 Stem::Stem(int c)
18 {
19     minnote = 1000;             // invalid values
20     maxnote = -1000;
21     bot = top = 0;
22     flag = 4;
23     dir =0;
24     staff_center=c;
25     stemlen=0;
26     print_flag=true;
27     stem_xoffset=0;
28 }
29
30
31 void
32 Stem::set_stemend(Real se)
33 {
34     // todo: margins
35     assert((dir > 0 && se >= maxnote) || (se <= minnote && dir <0));
36     
37     top = (dir < 0) ? maxnote           : se;
38     bot = (dir < 0) ? se  : minnote;
39     flag = dir*ABS(flag);
40 }
41
42 void
43 Stem::add(Notehead *n)
44 {
45     if (n->balltype == 1)
46         return;
47     int p = n->position;
48     if ( p < minnote)
49         minnote = p;
50     if ( p> maxnote)
51         maxnote = p;
52 }
53 void
54 Stem::print()const
55 {
56     mtor << "Stem minmax=["<< minnote<<","<<maxnote<<"], flag: "<<flag;
57     Item::print();
58 }
59
60 void
61 Stem::set_default_dir()
62 {
63     Real mean = (minnote+maxnote)/2;
64     dir = (mean > staff_center) ? -1: 1;
65 }
66
67 void
68 Stem::set_default_stemlen()
69 {
70     if (!dir)
71         set_default_dir();
72
73     int stafftop = 2*staff_center;
74     stemlen = STEMLEN  + (maxnote - minnote);
75     
76     // uhh... how about non 5-line staffs?      
77     if (maxnote < -2 && dir == 1){
78         int t = staff_center - staff_center/2; 
79         stemlen = t - minnote +2;
80     } else if (minnote > stafftop + 2 && dir == -1) {
81         int t = staff_center + staff_center/2;
82         stemlen = maxnote -t +2;
83     }
84
85     assert(stemlen);
86 }
87
88
89 void
90 Stem::set_default_extents()
91 {
92     assert(minnote<=maxnote);
93
94     if (!stemlen)
95         set_default_stemlen();
96
97     set_stemend((dir< 0) ? maxnote-stemlen: minnote +stemlen);
98     if (dir > 0){       
99         stem_xoffset = paper()->note_width();
100     }
101 }
102
103 void
104 Stem::postprocess()
105 {
106     set_default_extents();
107     brew_molecole();
108 }
109
110 Interval
111 Stem::width()const
112 {
113     if (!print_flag || ABS(flag) <= 4)
114         return Interval(0,0);   // TODO!
115     Paperdef*p= paper();
116     return p->lookup_->flag(flag).dim.x;
117 }
118
119 void
120 Stem::brew_molecole()
121 {
122     assert(pstaff_);
123     assert(bot!=top);
124     assert(!output);
125     
126     Paperdef *p =paper();
127     Parametric_symbol *stem = p->lookup_->stem();
128     
129     Real dy = p->interline()/2;
130     String y1 =print_dimen( dy * bot);
131     String y2 = print_dimen(dy * top);
132     Symbol ss =stem->eval(y1,y2);
133     delete stem;
134     
135     output = new Molecule(Atom(ss));
136
137     if (print_flag&&ABS(flag) > 4){
138         Symbol fl = p->lookup_->flag(flag);
139         Molecule m(fl);
140         if (flag < -4){         
141             output->add_bot(m);
142         } else if (flag > 4) {
143             output->add_top(m);
144         } else
145             assert(false); 
146     }
147
148     output->translate(Offset(stem_xoffset,0));
149
150 }
151
152 Real
153 Stem::hpos()const
154 {
155     return pcol_->hpos + stem_xoffset;
156 }