Score_commands 1
Note_req 1
Rhythmic_req 1
-Rest_req 1
\ No newline at end of file
+Rest_req 1
+delete_identifiers 1
+++ /dev/null
-CODING STANDARDS:
-
-Functions and methods do not return errorcodes, but use assert for
-checking status.
-
-INDENTATION, in emacs:
-
-
-(add-hook 'c-mode-hook
- '(lambda ()(setq c-basic-offset 4)))
-
-
-(add-hook 'c++-mode-hook
- '(lambda() (c-set-style "Stroustrup")
- )
- )
-
-
-CLASSES and TYPES:
-
- This_is_a_class
-
-DATA MEMBERS
-
- Class:member
-
-if the member's name resembles its type, then we use
-
- Class Fubular { ..}
-
- Class::fubular_
-
-COMMENTS
-
-/// short description
-class Class {
- ///
- Data data_member_;
- /**
- ..
- */
-
- /****************/
-
- /// short memo
- member();
- /**
- long doco of member()
- */
-};
-/**
- Class documentation.
-*/
-
-Unfortunately most of the code isn't really documented that good.
\ No newline at end of file
--- /dev/null
+CODING STANDARDS:
+
+Functions and methods do not return errorcodes, but use assert for
+checking status.
+
+INDENTATION, in emacs:
+
+
+(add-hook 'c-mode-hook
+ '(lambda ()(setq c-basic-offset 4)))
+
+
+(add-hook 'c++-mode-hook
+ '(lambda() (c-set-style "Stroustrup")
+ )
+ )
+
+
+CLASSES and TYPES:
+
+ This_is_a_class
+
+DATA MEMBERS
+
+ Class:member
+
+if the member's name resembles its type, then we use
+
+ Class Fubular { ..}
+
+ Class::fubular_
+
+COMMENTS
+
+/// short description
+class Class {
+ ///
+ Data data_member_;
+ /**
+ ..
+ */
+
+ /****************/
+
+ /// short memo
+ member();
+ /**
+ long doco of member()
+ */
+};
+/**
+ Class documentation.
+*/
+
+Unfortunately most of the code isn't really documented that good.
\ No newline at end of file
--- /dev/null
+
+DOCFILES=CodingStyle algorithms Makefile
+dist:
+ ln $(DOCFILES) $(DDIR)/Documentation/
\ No newline at end of file
--- /dev/null
+Date: Tue, 5 Nov 1996 00:01:32 +0100
+From: Werner Icking <Werner.Icking@gmd.de>
+To: hanwen@stack.urc.tue.nl
+Cc: dsimons@logicon.com
+Subject: Re: font sizes.
+
+> Date: Mon, 4 Nov 1996 22:37:54 +0100 (MET)
+> From: Han-Wen Nienhuys <hanwen@stack.urc.tue.nl>
+> >
+> >There were different schemes when music was typeset by hand. If I remember
+> >right Harder uses another scheme that Gomberg. Both scheme may be used
+>
+> Who are Harder and Gomberg? Do you have references?
+
+Both are mentioned in the master thesis by Steinbach & Schofer who
+invented M(u)TeX, the grandmother of all M...TeXs. The Musiclibrary
+in Bonn has the harder (printed in 1948?) and there are not many books
+I liked more to own.
+
+The master thesis should be available at the CTAN archives under MuTeX
+or MTEX maybe subdirectory DIPL (for Diplom). I have the TEX-source
+and I may pack it to ftp.gmd.de if you are interested and can't find it
+on CTAN.
+================================================================
+
+[breaking lines]
+>
+>Incidentally, I use a different approach in PMX, starting with the
+>total number of systems for the piece instead of assuming a starting
+>physical value for \elemskip. That's equivalent to setting the
+>physical length of the whole piece if laid out in one long line.
+>Knowing the total amount of scalable and fixed space I compute a
+>starting physical value for \elemskip. I use that to get how many
+>bars go in the first line. Then I force a line break there, remove
+>those bars and their scalable and fixed space from the accounting, and
+>start over with the second line, etc.
+
+
+Since you are getting into technical details, I will show mine too: I
+think my way is the most elegant algorithm i've seen so far. Some
+terminology: I call a vertical group of symbols (notes) which start at
+the same time a "column". Each line of a score has notes in it,
+grouped in columns. The difference in starting time between those
+columns makes it possible to determine ideal distances between those
+columns.
+
+Example:
+
+ time ----->
+
+ col1 col2 col3 col4
+
+
+voice1 1 1
+
+voice2 2 2 2 2
+
+
+(1 is a whole note, 2 a half note.)
+
+time_difference (col1 , col2) = 0.5 wholes,
+time_difference (col1 , col3) = 1 wholes,
+time_difference (col2 , col3) = 0.5 wholes,
+etc.
+
+these differences are translated into ideal distances (these translations
+have been the subject of discussion in this thread).
+
+ distance (col1,col2) = 10 pt
+ distance (col1,col3) = 14.1 pt
+ distance (col2,col3) = 10 pt
+ etc.
+
+as you can see, these distance are conflicting. So instead of
+satisfying all those ideals simultaneously, a compromise is sought.
+
+This is Columbus' egg: LilyPond attaches "springs" to each
+column-pair. each spring has an equilibrium-position which is equal to
+the above mentioned distance, so
+
+ spring (col1, col2) and spring(col2,col3) try to push column 1
+and 3 away (to a distance of 20pt) from each other, whereas the spring
+between col 1 and col 3 tries to pull those two together (to a
+distance of 14.1 pt). The net result of this pushing and pulling is an
+equilibrium situation (the pushing cancels the pulling), which can be
+calculated as the solution of Quadratic program: it is the solution
+with minimum potential energy, for you physicists out there.
+
+This algorithm for doing one line, gives a "badness" parameter for
+each line (the potential energy). Now one can use TeX's algorithm for
+making paragraphs (using this new version of "badness"): one should
+try to minimise the overall badness of a paragraph. LilyPond also uses the
+concept of pre- and post-breaks.
+
+(actually, it is a bit more complicated: each column also has a
+minimum distance to other columns, to prevent symbols from running
+into symbols of other columns.)
+
MAJVER=0
MINVER=0
-PATCHLEVEL=7
+PATCHLEVEL=8
+
+TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
#
#
#dist
+.EXPORT_ALL_VARIABLES:
DOCDIR=docdir
VERSION=$(MAJVER).$(MINVER).$(PATCHLEVEL)
SCRIPTS=make_version make_patch genheader
IFILES=dimen.tex symbol.ini suzan.ly maartje.ly\
lilyponddefs.tex test.tex .dstreamrc
-OFILES=Makefile Sources.make
-DOC=COPYING README TODO CodingStyle
-DFILES=$(hdr) $(mycc) $(othersrc) $(OFILES) $(IFILES) $(SCRIPTS) $(DOC)
+OFILES=Makefile Sources.make COPYING README
+DFILES=$(hdr) $(mycc) $(othersrc) $(OFILES) $(IFILES) $(SCRIPTS)
#compiling
LOADLIBES=-L$(FLOWERDIR) -lflower
lexer.cc: lexer.l
$(FLEX) -+ -t $< > $@
-DDIR=$(DNAME)
+DDIR=$(TOPDIR)/$(DNAME)
+SUBDIRS=Documentation
dist:
-mkdir $(DDIR)
ln $(DFILES) $(DDIR)/
- tar cfz $(DNAME).tar.gz $(DDIR)/
+ for a in $(SUBDIRS); \
+ do mkdir $(DDIR)/$$a; \
+ $(MAKE) -C $$a dist;\
+ done
+ tar cfz $(DNAME).tar.gz $(DNAME)/
rm -rf $(DDIR)/
HOW DOES IT WORK
-Use The Source, Luke. If you don't know C++, you can try editing
+* Use The Source, Luke. If you don't know C++, you can try editing
.dstreamrc for copious debugging output.
+
+* see also the subdir Documentation
+
+* The source is commented in the DOC++ style.
+Check out doc++ at
+
+ http://www.ZIB-Berlin.DE/VisPar/doc++/doc++.html
# -*- Makefile-*-
-# sourcefiles to be shipped. Also for depedencies
+# sourcefiles to be shipped. Also for dependencies
hdr= qlp.hh linespace.hh qlpsolve.hh\
pcol.hh proto.hh pstaff.hh line.hh\
misc.hh score.hh notename.hh lexer.hh symtable.hh\
symbol.hh main.hh dimen.hh paper.hh lookupsyms.hh\
sccol.hh stcol.hh scommands.hh melodicstaff.hh\
- identifier.hh simplestaff.hh spanner.hh stem.hh
+ identifier.hh simplestaff.hh spanner.hh stem.hh\
+ notehead.hh
mycc= qlp.cc qlpsolve.cc \
break.cc linespace.cc molecule.cc line.cc\
dimen.cc paper.cc lookupsyms.cc scommands.cc\
sccol.cc stcol.cc getcommands.cc simplestaff.cc\
melodicstaff.cc simpleprint.cc stem.cc\
- spanner.cc\
+ spanner.cc notehead.cc\
template1.cc template2.cc template3.cc\
version.cc
\ No newline at end of file
+++ /dev/null
- * clefs
-
- * beam
-
- * fonttables -> fontdims
-
- * clear IDENTIFIERs
-
- * Paperdef -> fontsize .
-
- * merge Paper, Lookup, Outputfile, and Symtable.
-
- * all places in the code marked TODO! and ugh/ARGH
#include "pscore.hh"
#include "staff.hh"
#include "paper.hh"
-#include "misc.hh"
#include "sccol.hh"
#include "debug.hh"
if (sc->musical)
for (int i=0; i < sc->durations.sz(); i++) {
Real d = sc->durations[i];
- Real dist = duration_to_idealspace(d, paper_->whole_width);
+ Real dist = paper_->duration_to_dist(d);
PCol * c2 = find_col(sc->when + d,true)->pcol;
connect_nonmus(sc->pcol, c2, dist);
c2 = find_col(sc->when + d,false)->pcol;
MAJVER=1
MINVER=0
-PATCHLEVEL=7
+PATCHLEVEL=8
PACKAGENAME=flower
VERSION=$(MAJVER).$(MINVER).$(PATCHLEVEL)
rm -f $(obs) $(staticlib)
realclean: clean
rm -f depend
-DFILES=$(hh) $(cc) $(inl) $(templatecc) Makefile Sources.make TODO
+DFILES=$(hh) $(cc) $(inl) $(templatecc) Makefile Sources.make TODO README
DDIR=$(DNAME)
dist:
--- /dev/null
+This library contains some general purpose routines which aren't
+standardised yet. It was written by:
+
+ Han-Wen Nienhuys <hanwen@stack.nl>
+
+and
+
+ Jan Nieuwenhuizen <jan@digicash.com>
+
+It is licensed under the GNU GPL.
\ No newline at end of file
cc=lgetopt.cc string.cc dataf.cc textdb.cc unionfind.cc \
smat.cc matrix.cc choleski.cc vector.cc dstream.cc\
- matdebug.cc
+ matdebug.cc interval.cc
templatecc=cursor.cc list.cc tsmat.cc plist.cc
inl=findcurs.inl link.inl list.inl cursor.inl plist.inl
string.hh stringutil.hh vray.hh textdb.hh textstr.hh assoc.hh\
findcurs.hh unionfind.hh compare.hh handle.hh matrix.hh\
smat.hh vsmat.hh vector.hh real.hh choleski.hh\
- tsmat.hh tvsmat.hh plist.hh associter.hh\
+ tsmat.hh tvsmat.hh plist.hh associter.hh fproto.hh\
+ interval.hh
* efficient copy cons for List
+ * extend Interval
+
* change String::pos
s[s.pos('%')] == '%'
* use template handle in handle.hh for strings.
- * Restricted cursor/list: make sublist from a list, and use rcursor as if list is as big as the sublist.
+ * Restricted cursor/list: make sublist from a list, and use rcursor
+as if list is as big as the sublist.
- * move towards gnu?
+ * move towards gnu or STL?
parsestream.h
vector.h
return r;
}
-
+/*
+ warning: can't use Cursor::operator == (Cursor),
+ since it uses Cursor::operator-(Cursor)
+ */
template<class T>
int
-Cursor<T>::operator-(Cursor<T> c) const
+Cursor<T>::operator-(Cursor<T> rhs) const
{
- assert(c.list == list);
+ assert(rhs.list == list);
int dif = 0;
- Cursor<T> upward(c);
- while (upward.ok() && upward.pointer_ != pointer_) {
- upward++;
+
+ // search from *this on further up (positive difference)
+ Cursor<T> c(*this);
+ while (c.ok() && c.pointer_ != rhs.pointer_) {
+ c--;
dif++;
}
- if (upward.ok())
- return dif;
+ if (c.ok())
+ goto gotcha; // so, sue me.
+
+ // search in direction of bottom. (negative diff)
dif =0;
- while (c.ok()&& c.pointer_ != pointer_) {
+ c=*this;
+ while (c.ok() && c.pointer_ !=rhs.pointer_) {
dif --;
- c--;
+ c++;
}
assert(c.ok());
+
+gotcha:
+ assert((*this - dif).pointer_ == c.pointer_);
return dif;
}
template<class T>
inline int cursor_compare(Cursor<T> a,Cursor<T>b)
{
- return b-a;
+ return a-b;
}
template_instantiate_compare(Cursor<T>, cursor_compare, template<class T>);
--- /dev/null
+/*
+ fproto.hh -- typenames in flowerlib
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef FPROTO_HH
+#define FPROTO_HH
+
+template<class T> struct svec;
+template<class T> struct sstack;
+template<class T,class K> struct Assoc;
+template<class T> struct List;
+template<class T> struct PointerList;
+template<class T> struct IPointerList;
+template<class T> struct Cursor;
+template<class T> struct PCursor;
+template<class T> struct Link;
+template<class T> struct Handle ;
+
+
+struct Assoc_ent_ ;
+struct Assoc ;
+struct Assoc_iter ;
+struct Choleski_decomposition ;
+struct Interval ;
+struct long_option_init ;
+struct Getopt_long ;
+struct Matrix ;
+struct StringData ;
+struct String_handle ;
+struct virtual_smat ;
+struct Vector ;
+class Text_stream;
+class Data_file ;
+struct Text_db;
+#endif // FPROTO_HH
+
--- /dev/null
+#include <assert.h>
+#include "interval.hh"
+#include <math.h>
+
+const Real INFTY = HUGE;
+
+void
+Interval::set_empty() {
+ min = INFTY;
+ max = -INFTY;
+}
+
+Real
+Interval::length() const {
+ assert(max >= min);
+ return max-min;
+}
+
--- /dev/null
+/*
+ interval.hh -- part of flowerlib
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef INTERVAL_HH
+#define INTERVAL_HH
+
+#include <assert.h>
+#include "real.hh"
+
+
+/// a Real interval
+struct Interval {
+ Real min, max;
+
+ void translate(Real t) {
+ min += t;
+ max += t;
+ }
+ Real operator[](int j) {
+ if (j==-1)
+ return min;
+ else if (j==1)
+ return max;
+ else
+ assert(false);
+ return 0.0;
+
+ }
+ void unite(Interval h) {
+ if (h.min<min)
+ min = h.min;
+ if (h.max>max)
+ max = h.max;
+ }
+ Real length() const;
+ void set_empty() ;
+ bool empty() { return min > max; }
+ Interval() {
+ set_empty();
+ }
+ Interval(Real m, Real M) {
+ min =m;
+ max = M;
+ }
+ Interval &operator += (Real r) {
+ min += r;
+ max +=r;
+ return *this;
+ }
+};
+
+
+#endif // INTERVAL_HH
+
+
process command line, GNU style.
- this is (Copyleft) 1996, Han-Wen Nienhuys, <hanwen@stack.urc.tue.nl>
+ this is (Copyleft) 1996, Han-Wen Nienhuys, <hanwen@stack.nl>
*/
#include <stdio.h>
#include <iostream.h>
PCursor<T> operator -( int no) const {
return PCursor<T> (Cursor<void*>::operator-(no));
}
-
+ int operator -(PCursor<T> op) const {
+ return Cursor<void*>::operator-(op);
+ }
/// make cursor with #no# items further
PCursor<T> operator +( int no) const {
return PCursor<T> (Cursor<void*>::operator+(no));
template<class T>
inline int pcursor_compare(PCursor<T> a,PCursor<T>b)
{
- return cursor_compare(Cursor<void*>(b),Cursor<void*> (a));
+ return cursor_compare(Cursor<void*>(a),Cursor<void*> (b));
}
#include "compare.hh"
void PL_copy(IPointerList<T*> &dst,IPointerList<T*> const&src);
-#define PL_instantiate(a) L_instantiate(a *); template class PointerList<a*>
+#define PL_instantiate(a) template class PointerList<a*>
#define IPL_instantiate(a) PL_instantiate(a); template class IPointerList<a*>
#include "plist.inl"
+#ifndef TEXTSTR_HH
+#define TEXTSTR_HH
+
#include <stdio.h>
#include <ctype.h>
exit(1);
}
};
+#endif
Identifier::~Identifier()
-{
+{
}
Staff_id::~Staff_id()
{
delete staff();
}
+
+Voice_id::~Voice_id()
+{
+ delete voice();
+}
Identifier(String n) ;
virtual ~Identifier();
virtual Staff * staff() { assert(false); }
+ virtual Voice * voice() { assert(false); }
};
struct Staff_id : Identifier {
~Staff_id();
};
-
-
+struct Voice_id : Identifier {
+ Voice_id(String s, Voice*st):Identifier(s) { data = st; }
+ virtual Voice * voice() { return (Voice*)data; }
+ ~Voice_id();
+};
#endif // IDENTIFIER_HH
#include "molecule.hh"
#include "pcol.hh"
+void
+Item::postprocess()
+{
+ // default: do nothing
+}
+
+
+void
+Item::preprocess()
+{
+ // default: do nothing
+}
+
String
Item::TeXstring() const
{
#include "glob.hh"
#include "boxes.hh"
#include "string.hh"
-#include "tex.hh"
-
/// a horizontally fixed size element of the score
struct Item {
*/
/****************/
+
+ /// do calculations after determining horizontal spacing
+ virtual void postprocess();
+ /// do calculations before determining horizontal spacing
+ virtual void preprocess();
+ /**
+ This is executed directly after the item is added to the
+ PScore
+ */
+
virtual Interval width() const;
virtual Interval height() const;
String TeXstring () const ;
void print()const;
virtual ~Item();
};
-/** An item must be part of a Column
+/** Item is the datastructure for printables whose width is known
+ before the spacing is calculated
+
+ NB. This doesn't mean an Item has to initialize the output field before
+ spacing calculation.
+
*/
Identifier* lookup_identifier(String s);
void add_identifier(Identifier*i);
+void delete_identifiers();
#endif
\vskip 40pt\par\vbox{\hbox to 0pt{\vrule width30pt height1pt\hss}}\par\vskip 40pt
}
\def\interscoreline{\beauty}
-%
-% a staffsymbol with #1 lines, width #2
-% bottom at baseline
-\def\linestafsym#1#2{\vbox to 0pt{\hbox to 0pt%
- {\vbox to 0pt{\vss%
- \kern-\interstaffrule
+
+
+\def\lines#1#2{%
+ \vbox{\kern-\interstaffrule
\n=0\nointerlineskip%
\loop\ifnum\n<#1\advance\n by1%
- \kern\interstaffrule \hrule height \staffrulethickness width#2
+ \kern\interstaffrule
+ \hrule height \staffrulethickness width#2
\repeat
- }%
-\hss}}}
+ }}
+
+\def\toplines#1{ % why space needed here?
+ \vbox to 0pt{\hbox{\kern-6pt\lines{#1}{12pt}}\vss}}
+\def\botlines#1{ % idem ditto
+ \vbox to 0pt{\vss\hbox{\kern-6pt\lines{#1}{12pt}}}}
+
+%
+% a staffsymbol with #1 lines, width #2
+% bottom at baseline
+\def\linestafsym#1#2{\hbox to 0pt{\vbox to 0pt{\vss\lines{#1}{#2}}\hss}}
\def\vcenter#1{\vbox to 0pt{\vss #1\vss}}
\def\topalign#1{\vbox to 0pt{#1\vss}}
#include "symtable.hh"
#include "dimen.hh"
#include "tex.hh"
+
void
Lookup::parse(Text_db&t)
{
return (*symtables_)("flags")->lookup(j);
}
+Symbol
+Lookup::streepjes(int i)
+{
+ assert(i);
+
+ int arg;
+ String idx ;
+ if (i<0) {
+ idx = "botlines";
+ arg = -i;
+ }else {
+ arg = i;
+ idx = "toplines";
+ }
+ Symbol ret = (*symtables_)("streepjes")->lookup(idx);
+
+ svec<String> a;
+ a.add(arg);
+ ret.tex = substitute_args(ret.tex, a);
+
+ return ret;
+}
+
/****************************************************************/
// bare bones.
Parametric_symbol *linestaff(int n);
Parametric_symbol *meter(String);
Parametric_symbol *stem();
+ Symbol streepjes(int pos);
+ /**
+ pos == 3 : 3 lines above staff (extending below note)
+
+ pos == -3: below staff
+ */
+
Symbol ball(int);
Symbol flag(int);
Symbol rest(int);
}
melody=
melodicstaff {
- voice { $ c2.. r8 r4 r8 r16 r32 r32 d8 e8 f8 g8 ''fis1 a8 b8 'c8 c8 `c8 ``c8 c4 c4 c4 c4 $ }
+ voice { $ ''c2.. r8 r4 r8 r16 r32 r32 d8 e8 f8 g8 ''fis1 a8 b8 'c8 c8 ''c8 ```c8 c4 c4 c4 c4 $ }
}
score {
paper {
#include "melodicstaff.hh"
#include "stem.hh"
-
+#include "notehead.hh"
#include "paper.hh"
#include "molecule.hh"
#include "linestaff.hh"
void
Melodic_column::typeset_req(Request *rq)
{
- Item *i =new Item;
- Molecule*m=create_req_mol(rq);
-
+ Item *i ;
if (rq->note()) {
- int h = rq->note()->height();
- Real dy = staff_->paper()->interline()/2;
- m->translate(Offset(0,(h-BOTTOM_POSITION)*dy));
+ Notehead *n =new Notehead((NO_LINES-1)*2);
+ n->balltype = rq->rhythmic()->balltype;
+ n->dots = rq->rhythmic()->dots;
+ n->position = rq->note()->height() - BOTTOM_POSITION;
+ i = n;
+ } else if (rq->rest()) {
+ i =new Item;
+ Molecule*m=create_req_mol(rq);
+ i->output=m;
}
- i->output = m;
typeset_item(i);
}
int n = the_note->note()->height()-BOTTOM_POSITION;
s->minnote =s->maxnote=n;
s->flag = rq->stem_number;
- s->calculate();
- typeset_item(s);
-
- s->brew_molecole();
+ typeset_item(s);
}
/*
return i;
}
-double log2(double x) {
- return log(x) /log(2.0);
-}
-
-
-// golden ratio
- const Real PHI = (1+sqrt(5))/2;
-const double ENGRAVERS_SPACE = PHI;
-
-
-
-
-Real
-duration_to_idealspace(Real d, Real w)
-{
- // see Roelofs, p. 57
- return w * pow(ENGRAVERS_SPACE, log2(d));
-}
-
-
-
-
#ifndef MISC_HH
#define MISC_HH
-#include "real.hh"
-int intlog2(int d);
-Real duration_to_idealspace(Real d,Real w);
+
+
+
#endif
--- /dev/null
+#include "notehead.hh"
+#include "dimen.hh"
+#include "debug.hh"
+#include "pstaff.hh"
+#include "pscore.hh"
+#include "paper.hh"
+#include "lookupsyms.hh"
+#include "molecule.hh"
+
+
+Notehead::Notehead(int ss)
+{
+ staff_size=ss;
+ position = 0;
+ balltype = 0;
+ dots = 0;
+}
+
+void
+Notehead::print()const
+{
+ mtor << "Head "<<balltype<<", position = "<< position << "dots " << dots;
+ Item::print();
+}
+
+void
+Notehead::preprocess()
+{
+ brew_molecole();
+}
+
+void
+Notehead::brew_molecole()
+{
+ assert(pstaff_);
+ assert(!output);
+
+ Paperdef *p = pstaff_->pscore_->paper_;
+
+ Real dy = p->interline()/2;
+ Symbol s = p->lookup_->ball(balltype);
+
+ output = new Molecule(Atom(s));
+ if (dots) {
+ Symbol d = p->lookup_->dots(dots);
+ Molecule dm;
+ dm.add(Atom(d));
+ if (!(position %2))
+ dm.translate(Offset(0,dy));
+ output->add_right(dm);
+ }
+ bool streepjes = (position<-1)||(position > staff_size+1);
+ if (streepjes) {
+ int dir = sgn(position);
+ int s =(position<-1) ? -((-position)/2): (position-staff_size)/2;
+ Symbol str = p->lookup_->streepjes(s);
+ Molecule sm;
+ sm.add(Atom(str));
+ if (position % 2)
+ sm.translate(Offset(0,-dy* dir));
+ output->add(sm);
+ }
+
+
+ output->translate(Offset(0,dy*position));
+}
+
--- /dev/null
+/*
+ notehead.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef NOTEHEAD_HH
+#define NOTEHEAD_HH
+#include "item.hh"
+
+/// ball at the end of the stem
+struct Notehead : public Item
+{
+ int position;
+ int staff_size;
+ int dots;
+ int balltype;
+
+ /****************/
+ void preprocess();
+
+ Notehead(int staff_size);
+ /**
+ position of top line (5 linestaff: 8)
+ */
+ void print()const;
+private:
+ void brew_molecole();
+};
+/**
+ takes care of:
+
+ * help lines
+ * proper placing of dots
+
+ */
+#endif // NOTEHEAD_HH
+
+#include <math.h>
+
#include "paper.hh"
#include "debug.hh"
#include "lookupsyms.hh"
#include "dimen.hh"
#include "textdb.hh"
+double log2(double x) {
+ return log(x) /log(2.0);
+}
+
+
+// golden ratio
+const Real PHI = (1+sqrt(5))/2;
+
+// see Roelofs, p. 57
+Real
+Paperdef::duration_to_dist(Real d)
+{
+ return whole_width * pow(geometric_, log2(d));
+}
+
Paperdef::Paperdef()
{
- linewidth = convert_dimen(15,"cm"); // in cm for now
- whole_width= convert_dimen(2,"cm");
lookup_ = new Lookup();
parse();
-
+ linewidth = convert_dimen(15,"cm"); // in cm for now
+ whole_width= 6*note_width();
+ geometric_ = PHI;
}
void
Real linewidth;
/// how much space does a whole note take (ideally?)
Real whole_width;
+
+ // ideal = geometric_ ^ log2(duration)
+ Real geometric_;
/****************/
void parse();
Real standard_height()const;
Real note_width() const;
void print() const;
+ Real duration_to_dist(Real);
};
%token VOICE STAFF SCORE TITLE RHYTHMSTAFF BAR NOTENAME OUTPUT
%token CM IN PT MM PAPER WIDTH METER UNITSPACE SKIP COMMANDS
-%token MELODICSTAFF
+%token MELODICSTAFF GEOMETRIC START
%type <consstr> unit
%token <id> IDENTIFIER
$$ = new Staff_id(*$1, $3);
delete $1; // this sux
}
+ | NEWIDENTIFIER '=' voice_block {
+ $$ = new Voice_id(*$1, $3);
+ delete $1;
+ }
;
delete $3;
}
| paper_body UNITSPACE dim { $$->whole_width = $3; }
+ | paper_body GEOMETRIC REAL { $$->geometric_ = $3; }
;
dim:
voice_body:
- REAL voice_elts_dollar { $$ = $2; $$->start = $1; }
+ IDENTIFIER { $$ = new Voice(*$1->voice()); }
| voice_elts_dollar { $$ = $1; }
+ | voice_body START REAL { $$->start = $3; }
;
+
+
+
voice_elts_dollar:
'$' voice_elts '$' { $$ = $2; }
;
#endif
new_input(s);
yyparse();
+ delete_identifiers();
*mlog << "\n";
}
its.bottom().add(i);
s->add(i);
c->add(i);
+ i->preprocess();
}
void
#endif
}
+void
+PScore::preprocess()
+{
+#if 0
+ for (PCursor<Item*> ic(its); ic.ok(); ic++){
+ ic->preprocess();
+ }
+#endif
+}
+
+void
+PScore::postprocess()
+{
+ for (PCursor<Item*> ic(its); ic.ok(); ic++){
+ ic->postprocess();
+ }
+}
/****************************************************************/
svec<Item*> select_items(PStaff*, PCol*);
+
+ /// before calc_breaking
+ void preprocess();
void calc_breaking();
/**
lines contain the broken lines.
*/
+ /// after calc_breaking
+ void postprocess();
+
/// search all pcols which are breakable.
svec<const PCol *> find_breaks() const;
return s + octave*7;
}
-/****************************************************************/
Rhythmic_req::Rhythmic_req(Voice_element*v)
:Request(v)
{
balltype = 1;
dots = 0;
}
+
void
Rhythmic_req::print() const
{
mtor << '.';
mtor<<"\n";
}
+
void
Note_req::print() const
{
#include "molecule.hh"
+#include "notehead.hh"
#include "stem.hh"
#include "linestaff.hh"
#include "rhythmstaff.hh"
void
Rhythmic_column::typeset_req(Request *rq)
{
- Item *i =new Item;
- Molecule*m=create_req_mol(rq);
- i->output=m;
+ Item *i ;
+ if (rq->note()) {
+ Notehead *n =new Notehead(1);
+ n->balltype = rq->rhythmic()->balltype;
+ n->dots = rq->rhythmic()->dots;
+ n->position = 0;
+ i = n;
+ } else if (rq->rest()) {
+ i =new Item;
+ Molecule*m=create_req_mol(rq);
+ i->output=m;
+ }
typeset_item(i);
}
Stem * s = new Stem(0);
s->minnote = s->maxnote = 0;
s->flag = rq->stem_number;
- s->calculate();
typeset_item(s);
- s->brew_molecole();
}
/*
delete paper_;
paper_ = p;
}
+
void
Score::output(String s)
{
void
Score::process()
{
- *mlog << "Processing ...";
+ *mlog << "Processing ... ";
set(commands_->parse(last()));
commands_->print();
clean_cols();
OK();
// print();
+
+ pscore_->preprocess();
*mlog << "Calculating ... ";
pscore_->calc_breaking();
+ pscore_->postprocess();
+
// TODO: calculate vertical structs
// TODO: calculate mixed structs.
*mlog << "\n";
Molecule *
Simple_column::create_req_mol(Request *rq)
{
+ assert(rq->rest());
Symbol s;
int dots=0;
-
- if (rq->note())
- s = staff_->paper()->lookup_->ball(rq->note()->balltype);
- else if (rq->rest())
+ if (rq->rest())
s = staff_->paper()->lookup_->rest(rq->rest()->balltype);
if (rq->rhythmic())
}
return m;
}
+
Molecule *
Simple_column::create_command_mol(Command *com)
{
return strets->eval(w).tex;
}
+// todo.
Spanner *
Spanner::broken_at(const PCol *c1, const PCol *c2) const
{
const PCol *left, *right;
Parametric_symbol *strets;
PStaff * pstaff_;
- /// clone a piece of this spanner.
- Spanner *broken_at(const PCol *c1, const PCol *c2) const;
+ /// clone a piece of this spanner.
+ virtual Spanner *broken_at(const PCol *c1, const PCol *c2) const;
/**
PRE
/****************/
String TeXstring () const ;
Spanner();
+ virtual void process();
};
/** Spanner should know about the items which it should consider:
e.g. slurs should be steep enough to "enclose" all those items. This
}
}
+void
+Stem::postprocess()
+{
+ calculate();
+ brew_molecole();
+}
+
Interval
Stem::width()const
{
Stem::brew_molecole()
{
assert(pstaff_);
- Paperdef *p = pstaff_->pscore_->paper_;
- Parametric_symbol *stem = p->lookup_->stem();
-
assert(bot!=top);
assert(!output);
+ Paperdef *p = pstaff_->pscore_->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 (ABS(flag) > 4){
#define STEM_HH
#include "item.hh"
+/// the rule attached to the ball
struct Stem : public Item {
// heads the stem encompasses (positions)
int minnote, maxnote;
// flagtype? 4 none, 8 8th flag, 0 = beam.
int flag;
-
/****************/
- void brew_molecole();
- void calculate();
+
+ void postprocess();
Stem(int center);
void print() const;
- Interval width() const;
+ Interval width() const;
+private:
+ void calculate();
+ void brew_molecole();
};
+/**
+ takes care of:
+
+ \begin{itemize}
+ \item the rule
+ \item the flag
+ \item up/down position.
+ \end{itemize}
+ */
+
#endif
4 \quartball 0pt 6pt -2.5pt 2.5pt
end
+table streepjes
+ toplines \toplines{%} -6pt 6pt 0pt 0pt
+ botlines \botlines{%} -6pt 6pt 0pt 0pt
+end
+
table bars
empty \emptybar 0pt 0pt 0pt 0pt
| \maatstreep 0pt 1pt -12pt 12pt
#include "string.hh"
#include "identifier.hh"
#include "keyword.hh"
+#include "associter.hh"
#include "parser.hh"
static Keyword_ent the_key_tab[]={
"skip", SKIP,
"commands", COMMANDS,
"staff", STAFF,
+ "geometric", GEOMETRIC,
0,0
} ;
{
the_id_tab[i->name] = i;
}
+
+void
+delete_identifiers()
+{
+
+ for (Assoc_iter<String,Identifier*> ai(the_id_tab); ai.ok(); ai++) {
+ mtor << "deleting: " << ai.key()<<'\n';
+ delete ai.val();
+ }
+}
#include "string.hh"
#include "boxes.hh"
+/// parameter substitution in TeXstrings
String
substitute_args(String source, svec<String> args);
/**
// print string. don't forget indent.
Tex_stream &
Tex_stream::operator<<(String s)
-{
+{
+
for (const char *cp = s; *cp; cp++) {
if (outputting_comment) {
*os << *cp;
nest_level--;
*os << *cp;
assert (nest_level >= 0);
- /* FALL THROUGH */
+ /* FALTHROUGH */
case '\n':
*os << "%\n";
Real when(const Voice_element*)const;
Real last() const;
Voice();
- Voice( Voice const&);
+ Voice(Voice const&);
void add(Voice_element*);
void print() const;
};