]> git.donarmstrong.com Git - lilypond.git/blobdiff - src/beam.cc
release: 0.0.20
[lilypond.git] / src / beam.cc
index 88dab8992d94d0d1d8853b07f42d3125fab924c6..85d5cc4812d58dab92f001d9e83976f1d9360754 100644 (file)
@@ -1,4 +1,6 @@
+#include "dimen.hh"
 #include "beam.hh"
+#include "misc.hh"
 #include "debug.hh"
 #include "symbol.hh"
 #include "molecule.hh"
@@ -7,7 +9,7 @@
 #include "stem.hh"
 #include "paper.hh"
 #include "lookup.hh"
-
+#include "grouping.hh"
 
 struct Stem_info {
     Real x;
@@ -20,20 +22,32 @@ struct Stem_info {
     Stem_info(){}
     Stem_info(const Stem*);
 };
+
 Stem_info::Stem_info(const Stem*s)
 {
     x = s->hpos();
     int dir = s->dir;
-    idealy  = MAX(dir*s->top, dir*s->bot);
-    miny = MAX(dir*s->minnote, dir*s-> maxnote);
+    idealy  = max(dir*s->top, dir*s->bot);
+    miny = max(dir*s->minnote, dir*s-> maxnote);
     assert(miny <= idealy);
     no_beams = s->flag;
 }
 
 /****************/
+Offset
+Beam::center()const
+{
+    if(!dir)
+        ((Beam*)this)->calculate();
+    Real w=width().length()/2;
+    return Offset(w,
+                  (left_pos + w* slope)*paper()->interline());
+}
+
 
 Beam::Beam()
 {
+    group = 0;
     slope = 0;
     left_pos = 0.0;
     dir =0;
@@ -60,6 +74,7 @@ Beam::set_default_dir()
        sc->dir = dir;
     }
 }
+
 /*
   should use minimum energy formulation (cf linespacing)
   */
@@ -92,15 +107,6 @@ Beam::solve_slope()
     left_pos *= dir;    
     slope *= dir;
     
-    {
-       Real inter =paper()->interline()/2;
-       Real unitslope = slope*inter;
-
-       // set beamslope, for setting stems correctly
-       // ignoring return.
-       Symbol sy = paper()->lookup_->beam(unitslope, width().length());
-       slope =unitslope / inter;
-    }
 }
 
 void
@@ -122,20 +128,53 @@ Beam::calculate()
        set_default_dir();
 
     solve_slope();
-    set_stemlens();
 }
 
 void
 Beam::process()
 {
     calculate();
+
     brew_molecule();
+    set_stemlens();
+}
+
+void
+Beam::set_grouping(Rhythmic_grouping def, Rhythmic_grouping cur)
+{
+    def.OK();
+    cur.OK();
+    assert(cur.children.sz() == stems.size());
+    
+    cur.split(def);
+    group = new Rhythmic_grouping(cur);
+    svec<int> b;
+    {
+       PCursor<Stem*> s(stems);
+       svec<int> flags;
+       for (; s.ok(); s++) {
+           int f = intlog2(abs(s->flag))-2;
+           assert(f>0);
+           flags.add(f);
+       }
+       int fi =0;
+       b= group->generate_beams(flags, fi);
+       b.insert(0,0);
+       b.add(0);
+       assert(stems.size() == b.sz()/2);
+    }
+
+    PCursor<Stem*> s(stems);
+    for (int i=0; i < b.sz() && s.ok(); i+=2, s++) {
+       s->beams_left = b[i];
+       s->beams_right = b[i+1];
+    }
 }
 
 
 // todo.
 Spanner *
-Beam::broken_at(const PCol *, const PCol *) const
+Beam::broken_at( PCol *, PCol *) const
 {
     return new Beam(*this);
 }
@@ -161,24 +200,97 @@ Beam::width() const
                     (*me->stems.bottom()) ->hpos() );
 }
 
+/*
+  beams to go with one stem.
+  */
+Molecule
+Beam::stem_beams(Stem *here, Stem *next, Stem *prev)
+{
+    assert( !next || next->hpos() > here->hpos()  );
+    assert( !prev || prev->hpos() < here->hpos()  );
+    Real dy=paper()->internote()*2;
+    Real stemdx = paper()->rule_thickness();
+    Real sl = slope*paper()->internote();
+    paper()->lookup_->beam(sl, convert_dimen(20,"pt"));
+    slope = sl /paper()->internote();
+    Molecule leftbeams;
+    Molecule rightbeams;
+
+    /* half beams extending to the left. */
+    if (prev) {
+       int lhalfs= lhalfs = here->beams_left - prev->beams_right ;
+       int lwholebeams= here->beams_left <? prev->beams_right ;
+       Real w = (here->hpos() - prev->hpos())/4;
+       Atom a =  paper()->lookup_->beam(sl, w);
+       a.translate(Offset (-w, -w * sl));
+       for (int j = 0; j  < lhalfs; j++) {
+           Atom b(a);
+           b.translate(Offset(0, -dir * dy * (lwholebeams+j)));
+           leftbeams.add( b );
+       }
+    }
+       
+    if (next){
+       int rhalfs = here->beams_right - next->beams_left;
+       int rwholebeams = here->beams_right <? next->beams_left; 
+
+       Real w = next->hpos() - here->hpos();
+       Atom a = paper()->lookup_->beam(sl, w + stemdx);
+       
+       int j = 0;
+       for (; j  < rwholebeams; j++) {
+           Atom b(a);
+           b.translate(Offset(0, -dir * dy * j));
+           rightbeams.add( b ); 
+       }
+       w /= 4;
+       a = paper()->lookup_->beam(sl, w);
+       
+       for (; j  < rwholebeams + rhalfs; j++) {
+           Atom b(a);
+           b.translate(Offset(0, -dir * dy * j));
+           rightbeams.add(b ); 
+       }
+       
+    }
+    leftbeams.add(rightbeams);
+    return leftbeams;
+}
+
+
 void
 Beam::brew_molecule()
 {
-    Real inter=paper()->interline()/2;
-    Real sl = slope*inter;
-    Real w =  width().length() + paper()->rule_thickness();
-    Symbol s = paper()->lookup_->beam(sl,w);
-
-    Atom a(s);
+    assert(left->line == right->line);
+    Real inter=paper()->internote();
+    output = new Molecule;
+    Real x0 = stems.top()->hpos();
     
-    Real dx = width().min -left->hpos;
-    a.translate(Offset(dx,left_pos*inter));
-    output = new Molecule(a);
+    for (PCursor<Stem*> i(stems); i.ok(); i++) {
+       PCursor<Stem*> p(i-1);
+       PCursor<Stem*> n(i+1);
+       Stem * prev = p.ok() ? p.ptr() : 0;
+       Stem * next = n.ok() ? n.ptr() : 0;
+
+       Molecule sb = stem_beams(i, next, prev);
+       Real  x = i->hpos()-x0;
+       sb.translate(Offset(x, (x * slope  + left_pos)* inter));
+       output->add(sb);
+    }
+    output->translate(Offset(x0 - left->hpos,0));
 }
 
 void
 Beam::print()const
 {
-    mtor << "Beam, slope " <<slope << "left ypos " << left_pos<<'\n';    
+#ifndef NPRINT
+    mtor << "{ slope " <<slope << "left ypos " << left_pos;
+    Spanner::print();
+    mtor << "}\n";
+#endif
 }
 
+Beam::~Beam()
+{
+    delete group;
+}