--- /dev/null
+/*
+ stem.hh --
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef STEM_HH
+#define STEM_HH
+#include "item.hh"
+
+/// the rule attached to the ball
+struct Stem : public Item {
+ // heads the stem encompasses (positions)
+ int minnote, maxnote;
+
+ /// false if in beam
+ bool print_flag;
+
+ /// needed for determining direction/length
+ int staff_center;
+
+ // extent of the stem (positions)
+ Real bot, top;
+ /**
+ fractional, since Beam has to adapt them.
+ */
+
+ Real stemlen;
+ // flagtype? 4 none, 8 8th flag, 0 = beam.
+ int flag;
+
+ ///geen gedonder, jij gaat onder
+ int dir;
+ /**
+ -1 stem points down, +1: stem points up
+ */
+
+ Real stem_xoffset;
+ /****************/
+
+ /// ensure that this Stem also encompasses the Notehead #n#
+ void add(Notehead*n);
+ Real hpos()const;
+ void set_stemend(Real);
+ void set_default_dir();
+ void set_default_stemlen();
+ void set_default_extents();
+ void postprocess();
+ Stem(int center);
+ void print() const;
+ Interval width() const;
+private:
+
+ void brew_molecole();
+};
+/**
+ takes care of:
+
+ \begin{itemize}
+ \item the rule
+ \item the flag
+ \item up/down position.
+ \end{itemize}
+ */
+
+#endif
--- /dev/null
+#include "stem.hh"
+#include "dimen.hh"
+#include "debug.hh"
+#include "paper.hh"
+#include "notehead.hh"
+#include "lookup.hh"
+#include "molecule.hh"
+#include "pcol.hh"
+
+const int STEMLEN=7;
+static int
+ABS(int i) {
+ return (i < 0)?-i:i;
+}
+
+
+Stem::Stem(int c)
+{
+ minnote = 1000; // invalid values
+ maxnote = -1000;
+ bot = top = 0;
+ flag = 4;
+ dir =0;
+ staff_center=c;
+ stemlen=0;
+ print_flag=true;
+ stem_xoffset=0;
+}
+
+
+void
+Stem::set_stemend(Real se)
+{
+ // todo: margins
+ assert((dir > 0 && se >= maxnote) || (se <= minnote && dir <0));
+
+ top = (dir < 0) ? maxnote : se;
+ bot = (dir < 0) ? se : minnote;
+ flag = dir*ABS(flag);
+}
+
+void
+Stem::add(Notehead *n)
+{
+ if (n->balltype == 1)
+ return;
+ int p = n->position;
+ if ( p < minnote)
+ minnote = p;
+ if ( p> maxnote)
+ maxnote = p;
+}
+void
+Stem::print()const
+{
+ mtor << "Stem minmax=["<< minnote<<","<<maxnote<<"], flag: "<<flag;
+ Item::print();
+}
+
+void
+Stem::set_default_dir()
+{
+ Real mean = (minnote+maxnote)/2;
+ dir = (mean > staff_center) ? -1: 1;
+}
+
+void
+Stem::set_default_stemlen()
+{
+ if (!dir)
+ set_default_dir();
+
+ int stafftop = 2*staff_center;
+ stemlen = STEMLEN + (maxnote - minnote);
+
+ // uhh... how about non 5-line staffs?
+ if (maxnote < -2 && dir == 1){
+ int t = staff_center - staff_center/2;
+ stemlen = t - minnote +2;
+ } else if (minnote > stafftop + 2 && dir == -1) {
+ int t = staff_center + staff_center/2;
+ stemlen = maxnote -t +2;
+ }
+
+ assert(stemlen);
+}
+
+
+void
+Stem::set_default_extents()
+{
+ assert(minnote<=maxnote);
+
+ if (!stemlen)
+ set_default_stemlen();
+
+ set_stemend((dir< 0) ? maxnote-stemlen: minnote +stemlen);
+ if (dir > 0){
+ stem_xoffset = paper()->note_width();
+ }
+}
+
+void
+Stem::postprocess()
+{
+ set_default_extents();
+ brew_molecole();
+}
+
+Interval
+Stem::width()const
+{
+ if (!print_flag || ABS(flag) <= 4)
+ return Interval(0,0); // TODO!
+ Paperdef*p= paper();
+ return p->lookup_->flag(flag).dim.x;
+}
+
+void
+Stem::brew_molecole()
+{
+ assert(pstaff_);
+ assert(bot!=top);
+ assert(!output);
+
+ Paperdef *p =paper();
+ Parametric_symbol *stem = p->lookup_->stem();
+
+ Real dy = p->interline()/2;
+ String y1 =print_dimen( dy * bot);
+ String y2 = print_dimen(dy * top);
+ Symbol ss =stem->eval(y1,y2);
+ delete stem;
+
+ output = new Molecule(Atom(ss));
+
+ if (print_flag&&ABS(flag) > 4){
+ Symbol fl = p->lookup_->flag(flag);
+ Molecule m(fl);
+ if (flag < -4){
+ output->add_bot(m);
+ } else if (flag > 4) {
+ output->add_top(m);
+ } else
+ assert(false);
+ }
+
+ output->translate(Offset(stem_xoffset,0));
+
+}
+
+Real
+Stem::hpos()const
+{
+ return pcol_->hpos + stem_xoffset;
+}