From: Han-Wen Nienhuys Date: Sat, 30 Nov 1996 11:09:32 +0000 (+0100) Subject: release: 0.0.9 X-Git-Tag: release/0.0.9 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=cd6fbd39e456ab3ff353c38fc5ae1997e61390f2;p=lilypond.git release: 0.0.9 --- diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle index c5d730c0a6..2c621ee06c 100644 --- a/Documentation/CodingStyle +++ b/Documentation/CodingStyle @@ -1,3 +1,5 @@ +-*-text-*- + CODING STANDARDS: Functions and methods do not return errorcodes, but use assert for @@ -19,14 +21,15 @@ INDENTATION, in emacs: CLASSES and TYPES: This_is_a_class + AClass_name (for Abbreviation_class_name) DATA MEMBERS - Class:member + Class::member -if the member's name resembles its type, then we use +if the member's name resembles its type, then I use - Class Fubular { ..} + class Fubular { ..} Class::fubular_ @@ -52,4 +55,37 @@ class Class { Class documentation. */ -Unfortunately most of the code isn't really documented that good. \ No newline at end of file +Unfortunately most of the code isn't really documented that good. + +CLASSNAMES (2) + +A lot of classes in LilyPond start with 'P', this is to distinguish +certain parts of LilyPond: the P stands for Printer, and the P-classes +are supposed to be more lowlevel than the others. Example: + + Staff uses PStaff, PScore and PCol to do the typesetting of +symbols. Staff is are the "brains" for PStaff + +NB: in PCursor (which is part of the library) P stands for PointerCursor + + +MEMBERS(2) + +Standard methods: + + ///check that *this satisfies its invariants, abort if not. + void OK() const + + /// print *this (and substructures) to debugging log + void print() const + + /// add some data to *this; + add( .. ) + /** + Presence of these methods usually imply that it is not feasible to this + via a constructor + */ + + /// replace some data of *this + set( .. ) + diff --git a/Documentation/Makefile b/Documentation/Makefile index da2847045e..e8adae90d7 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -1,4 +1,5 @@ -DOCFILES=CodingStyle algorithms Makefile +DOCFILES=CodingStyle algorithms Makefile breaking + dist: ln $(DOCFILES) $(DDIR)/Documentation/ \ No newline at end of file diff --git a/Documentation/breaking b/Documentation/breaking new file mode 100644 index 0000000000..ea1ada7e10 --- /dev/null +++ b/Documentation/breaking @@ -0,0 +1,38 @@ +[Source files: command.hh, scommands.cc] + +BREAKING, PREBREAK POSTBREAK, etc. + +So what's the deal with PREBREAK and POSTBREAK and all this +stuff? + +Let's take text as an example. In German some compound +words change their spelling if they are broken: "backen" becomes +"bak-ken". TeX has a mechanism to deal with this, you would define +the spelling of "backen" in TeX in this way + + \discretionary{bak-}{ken}{backen} + +These 3 arguments are called "prebreak", "postbreak" and "nobreak" +text. + +The same problem exists when typesetting music. If a line of music is +broken, the next line usually gets a clef. So in TeX terms, the clef +is a postbreak. The same thing happens with meter signs: Normally the +meter follows the bar. If a line is broken at that bar, the bar along +with the meter stays on the "last" line, but the next line also gets a +meter sign after the clef. Using the previous notation, + + \discretionary{bar meter}{clef meter}{ bar meter } + +In Lilypond, we have the same concepts (and the same +terminology). Each (nonrhythmic) symbol is typeset using a Command +(code: TYPESET). At a breakpoint, TYPESET commands can be grouped +using separators (in lower case): + + BREAK_PRE, typeset(bar), typeset(meter), + BREAK_MID, typeset(bar), typeset(meter), + BREAK_POST, typeset(clef), typeset(meter), BREAK_END + +The BREAK command sequence is terminated with BREAK_END, so other +commands (like INTERPRET) may follow this sequence. + diff --git a/Make.variables b/Make.variables new file mode 100644 index 0000000000..3d83d00ba7 --- /dev/null +++ b/Make.variables @@ -0,0 +1,71 @@ +#### +#### USER CONFIGURABLE +#### + +# speedy +#DEFINES=-DNDEBUG -DNPRINT -O2 + +# lots of debugging info +DEFINES=-g + +# turn off -pipe if linker doesn't support it +EXTRACXXFLAGS=-pipe -Wall -W -pedantic + +#### +#### EN USER CONFIGURABLE part. +#### + +# version info +MAJVER=0 +MINVER=0 +PATCHLEVEL=9 +VERSION=$(MAJVER).$(MINVER).$(PATCHLEVEL) + +# directories +TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi) +OBJECTDIR=objects +HEADERDIR=hdr +CCDIR=src + +vpath %.cc $(CCDIR) +vpath %.hh $(HEADERDIR) +vpath %.y $(CCDIR) +vpath %.l $(CCDIR) +vpath %.o $(OBJECTDIR) + +# +# +include Sources.make +progdocs=$(hdr) $(mycc) +gencc=parser.cc lexer.cc +cc=$(mycc) $(gencc) +obs=$(cc:.cc=.o) + + +#dist +.EXPORT_ALL_VARIABLES: + +DOCDIR=docdir + +PACKAGENAME=lilypond +DNAME=$(PACKAGENAME)-$(VERSION) + +# distribution files. +othersrc=lexer.l parser.y +SCRIPTS=make_version make_patch genheader +IFILES=dimen.tex symbol.ini kortjakje.ly maartje.ly\ + lilyponddefs.tex test.tex .dstreamrc +OFILES=Makefile Make.variables Sources.make COPYING README +DFILES=$(OFILES) $(IFILES) $(SCRIPTS) + +#compiling +LOADLIBES=-L$(FLOWERDIR) -lflower +FLOWERDIR=../flower + +CXXFLAGS=$(DEFINES) -I$(HEADERDIR) -I$(FLOWERDIR) $(EXTRACXXFLAGS) +FLEX=flex +BISON=bison +exe=$(PACKAGENAME) +OUTPUT_OPTION=$< -o $@ +DDIR=$(TOPDIR)/$(DNAME) +SUBDIRS=Documentation $(OBJECTDIR) $(CCDIR) $(HEADERDIR) diff --git a/Makefile b/Makefile index 2d8fa8a3ca..8f05ad90f8 100644 --- a/Makefile +++ b/Makefile @@ -1,55 +1,13 @@ -MAJVER=0 -MINVER=0 -PATCHLEVEL=8 - -TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi) - -# -# - -include Sources.make -progdocs=$(hdr) $(mycc) -gencc=parser.cc lexer.cc -cc=$(mycc) $(gencc) -obs=$(cc:.cc=.o) - - -#dist -.EXPORT_ALL_VARIABLES: - -DOCDIR=docdir -VERSION=$(MAJVER).$(MINVER).$(PATCHLEVEL) -PACKAGENAME=lilypond -DNAME=$(PACKAGENAME)-$(VERSION) -othersrc=lexer.l parser.y -SCRIPTS=make_version make_patch genheader -IFILES=dimen.tex symbol.ini suzan.ly maartje.ly\ - lilyponddefs.tex test.tex .dstreamrc -OFILES=Makefile Sources.make COPYING README -DFILES=$(hdr) $(mycc) $(othersrc) $(OFILES) $(IFILES) $(SCRIPTS) - -#compiling -LOADLIBES=-L$(FLOWERDIR) -lflower -FLOWERDIR=../flower -# speedy -#DEFINES=-DNDEBUG -DNPRINT -O2 -# lots of debugging info -DEFINES=-g - -CXXFLAGS=$(DEFINES) -I$(FLOWERDIR) -pipe -Wall -W -pedantic -FLEX=flex -BISON=bison -exe=$(PACKAGENAME) - -################################################################## +include Make.variables $(exe): $(obs) - $(CXX) -o $@ $(obs) $(LOADLIBES) + $(CXX) -o $@ $^ $(LOADLIBES) + clean: rm -f $(exe) *.o $(DOCDIR)/* core distclean: clean - rm -f TAGS depend version.hh $(gencc) .GENERATE *~ + rm -f depend version.hh $(gencc) .GENERATE *~ all: kompijl doc @@ -58,8 +16,13 @@ doc: -mkdir $(DOCDIR) doc++ -p -I -d $(DOCDIR) $(progdocs) -depend: Sources.make .GENERATE - $(CXX) $(CXXFLAGS) -MM $(cc) > $@ +depend: Sources.make .GENERATE + touch depend + $(MAKE) realdepend + + +$(OBJECTDIR)/%.o: $(CCDIR)/%.cc + $(CXX) -c $(CXXFLAGS) $(OUTPUT_OPTION) # hack to create these sources once, before the dependencies .GENERATE: @@ -68,25 +31,26 @@ depend: Sources.make .GENERATE $(MAKE) $(gencc) rm -f depend +realdepend: $(cc) + $(CXX) $(CXXFLAGS) -MM $^ | perl -ne 's/^(.+)\.o/'$(OBJECTDIR)'\/\1.o/; print;' > depend + include depend -parser.cc: parser.y +$(CCDIR)/parser.cc: parser.y $(BISON) -d $< - mv parser.tab.h parser.hh - mv parser.tab.c parser.cc + mv $(CCDIR)/parser.tab.h $(HEADERDIR)/parser.hh + mv $(CCDIR)/parser.tab.c $(CCDIR)/parser.cc parser.hh: parser.cc version.o: $(obs) version.hh version.hh: Makefile make_version - make_version $(MAJVER) $(MINVER) $(PATCHLEVEL) > $@ + make_version $(MAJVER) $(MINVER) $(PATCHLEVEL) > $(HEADERDIR)/$@ -lexer.cc: lexer.l +src/lexer.cc: lexer.l $(FLEX) -+ -t $< > $@ -DDIR=$(TOPDIR)/$(DNAME) -SUBDIRS=Documentation dist: -mkdir $(DDIR) ln $(DFILES) $(DDIR)/ @@ -98,7 +62,7 @@ dist: rm -rf $(DDIR)/ -TAGS: $(mycc) $(hdr) Sources.make - etags -CT $(mycc) $(hdr) - +TAGS: + $(MAKE) -C $(HEADERDIR) TAGS + $(MAKE) -C $(CCDIR) TAGS \ No newline at end of file diff --git a/README b/README index fd1c616b3a..cfee5ea3c9 100644 --- a/README +++ b/README @@ -6,7 +6,11 @@ This is a beta version of LilyPond (a music typesetter). This release is preliminary, please do not distribute. Please send your helpful comments and patches to me, - hanwen@stack.urc.tue.nl + hanwen@stack.urc.tue.nl + +LilyPond is updated very frequently, the latest version is always available at: + + ftp://pcnov095.win.tue.nl/pub/lilypond PREREQUISITES @@ -18,6 +22,14 @@ COMPILING You will need GNU C++ v2.7 or better and GNU make. If you actually want to use this, you'd better use the "speedy" compilation flags in the Makefile. +Do: + + tar zxf flower-1.11.9.tar.gz + mv flower-1.11.9 flower + cd flower; make; cd .. + tar zxf lilypond-1.2.13.tar.gz + cd lilypond-1.2.13 + make why G++ >= 2.7? LilyPond & flower lib uses builtin bool and typeof. @@ -32,20 +44,22 @@ what I type in my xterm: This is what the output looks like over here. -hw:~/musix/spacer$ lilypond maartje.ly -LilyPond version 0.0.6 compiled on Nov 2 1996 at 01:25:29 -Parsing ... [maartje.ly] +hw:~/musix/spacer$ lilypond kortjakje.ly +LilyPond version 0.0.9 compiled on Nov 7 1996 at 23:38:21 +Parsing ... [kortjakje.ly] +Processing ... Calculating ... output to lelie.uit... + hw:~/musix/spacer$ tex test This is TeX, Version 3.14159 (C version 6.1) (test.tex Hyphenation patterns for english, dutch, loaded. (lilyponddefs.tex) (lelie.uit) [1] ) -Output written on test.dvi (1 page, 1964 bytes). +Output written on test.dvi (1 page, 3076 bytes). Transcript written on test.log. + hw:~/musix/spacer$ xdvi test& -[1] 3130 -hw:~/musix/spacer$ +[1] 1667 PROBLEMS @@ -59,7 +73,8 @@ HOW DOES IT WORK * Use The Source, Luke. If you don't know C++, you can try editing .dstreamrc for copious debugging output. -* see also the subdir Documentation +* also the subdir Documentation/ it contains some in depth matter +on LilyPond algorithms * The source is commented in the DOC++ style. Check out doc++ at diff --git a/Sources.make b/Sources.make index 6e860c07d4..2894394f94 100644 --- a/Sources.make +++ b/Sources.make @@ -2,29 +2,32 @@ # sourcefiles to be shipped. Also for dependencies hdr= qlp.hh linespace.hh qlpsolve.hh\ - pcol.hh proto.hh pstaff.hh line.hh\ + pcol.hh proto.hh pstaff.hh scoreline.hh staffline.hh\ const.hh glob.hh molecule.hh boxes.hh pscore.hh item.hh tex.hh\ request.hh voice.hh command.hh staff.hh linestaff.hh \ tstream.hh rhythmstaff.hh\ parseconstruct.hh debug.hh globvars.hh keyword.hh\ misc.hh score.hh notename.hh lexer.hh symtable.hh\ - symbol.hh main.hh dimen.hh paper.hh lookupsyms.hh\ + symbol.hh main.hh dimen.hh paper.hh lookup.hh\ sccol.hh stcol.hh scommands.hh melodicstaff.hh\ identifier.hh simplestaff.hh spanner.hh stem.hh\ - notehead.hh + notehead.hh leastsquares.hh beam.hh rest.hh\ + swalker.hh bar.hh meter.hh mycc= qlp.cc qlpsolve.cc \ - break.cc linespace.cc molecule.cc line.cc\ - pscore.cc tex.cc item.cc pcol.cc staff.cc rhythmstaff.cc\ - score.cc note.cc main.cc misc.cc \ + break.cc linespace.cc molecule.cc staffline.cc\ + pscore.cc tex.cc item.cc pcol.cc staff.cc \ + rhythmstaff.cc score.cc note.cc main.cc misc.cc\ symbol.cc request.cc notename.cc voice.cc\ keyword.cc linestaff.cc table.cc command.cc\ warn.cc debug.cc symtable.cc boxes.cc\ pstaff.cc tstream.cc\ calcideal.cc scores.cc identifier.cc \ - dimen.cc paper.cc lookupsyms.cc scommands.cc\ + dimen.cc paper.cc lookup.cc scommands.cc\ sccol.cc stcol.cc getcommands.cc simplestaff.cc\ melodicstaff.cc simpleprint.cc stem.cc\ - spanner.cc notehead.cc\ + spanner.cc notehead.cc leastsquares.cc beam.cc\ + texbeam.cc rest.cc swalker.cc scoreline.cc\ + simplewalker.cc bar.cc meter.cc\ template1.cc template2.cc template3.cc\ version.cc \ No newline at end of file diff --git a/boxes.cc b/boxes.cc deleted file mode 100644 index ebfc08abfe..0000000000 --- a/boxes.cc +++ /dev/null @@ -1,31 +0,0 @@ -#include "boxes.hh" -#include "const.hh" - -void -Interval::set_empty() { - min = INFTY; - max = -INFTY; -} -Real -Interval::length() const { - return max-min; -} -Box::Box(svec s) -{ - assert(s.sz() == 4); - x.min = s[0]; - x.max = s[1]; - y.min = s[2]; - y.max = s[3]; -} - -Box::Box() -{ -} - -Box::Box(Interval ix, Interval iy) -{ - x = ix; - y = iy; -} - diff --git a/boxes.hh b/boxes.hh deleted file mode 100644 index 5d0be85452..0000000000 --- a/boxes.hh +++ /dev/null @@ -1,83 +0,0 @@ -/* - some 2D geometrical concepts -*/ - -#ifndef BOXES_HH -#define BOXES_HH - -#include "textdb.hh" -#include "real.hh" -#include "vray.hh" - -/// 2d vector -struct Offset { - Real x,y; - - Offset operator+(Offset o)const { - Offset r(*this); - r+=o; - return r; - } - - Offset operator+=(Offset o) { - x+=o.x; - y+=o.y; - return *this; - } - Offset(Real ix , Real iy) { - x=ix; - y=iy; - } - Offset() { - x=0.0; - y=0.0; - } -}; - -/// a Real interval -struct Interval { - Real min, max; - - void translate(Real t) { - min += t; - max += t; - } - - void unite(Interval h) { - if (h.minmax) - 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; - } -}; - - -/// a 4-tuple of #Real#s -struct Box { - Interval x, y; - - void translate(Offset o) { - x.translate(o.x); - y.translate(o.y); - } - void unite(Box b) { - x.unite(b.x); - y.unite(b.y); - } - Box(svec ); - Box(); - Box(Interval ix, Interval iy); -}; - - -#endif diff --git a/break.cc b/break.cc deleted file mode 100644 index 7d5a02a10e..0000000000 --- a/break.cc +++ /dev/null @@ -1,122 +0,0 @@ -/* - do calculations for breaking problem - - */ -#include "paper.hh" -#include "linespace.hh" -#include "debug.hh" -#include "line.hh" -#include "pscore.hh" - -// construct an appropriate Spacing_problem and solve it. -svec -PScore::solve_line(svec curline) const -{ - Spacing_problem sp; - - sp.add_column(curline[0], true, 0.0); - for (int i=1; i< curline.sz()-1; i++) - sp.add_column(curline[i]); - sp.add_column(curline.last(), true, paper_->linewidth); - - // misschien moeven uit Spacing_problem? - for (PCursor i(suz); i.ok(); i++) { - sp.add_ideal(i); - } - svec the_sol=sp.solve(); - return the_sol; -} - - -void -PScore::problem_OK() const -{ - if (!cols.size()) - error("PScore::problem_OK(): Score does not have any columns"); - PCursor start(cols); - PCursor end (((PScore*)this)->cols.bottom()); - - assert(start->breakable()); - assert(end->breakable()); -} - -struct Col_configuration { - svec line; - svec config; - Real energy; - - Col_configuration() { - energy = INFTY; - } - void add(const PCol*c) { line.add(c);} - void setsol(svec sol) { - config = sol; - energy = config.last(); - config.pop(); - } - void print() const { -#ifndef NPRINT - mtor << "energy : " << energy << '\n'; - mtor << "line of " << config.sz() << " cols\n"; -#endif - } -}; - -/// wordwrap type algorithm -/* el stupido. This should be done more accurately: - - It would be nice to have a Dynamic Programming type of algorithm - similar to TeX's - - */ - -void -PScore::calc_breaking() -{ - OK(); - problem_OK(); - PCursor curcol(cols); - - svec breakpoints(find_breaks()); - assert(breakpoints.sz()>=2); - for (int i=0 ; i < breakpoints.sz() -1; ) { - Col_configuration minimum; - Col_configuration current; - - // do another line - PCol *post = breakpoints[i]->postbreak; - current.add( post); - curcol++; // skip the breakable. - i++; - - while (i < breakpoints.sz()) { - - // add another measure. - while(breakpoints[i] !=curcol){ - - current.add(curcol); - curcol++; - } - current.add(breakpoints[i]->prebreak ); - current.setsol(solve_line(current.line)); - current.print(); - - if (current.energy < minimum.energy) { - minimum = current; - } else { // we're one col too far. - i--; - while (curcol != breakpoints[i]) - curcol --; - - break; - } - - current.line.last()=breakpoints[i]; - curcol ++; - i++; - } - mtor << "Adding line, next breakpoint " << i << '\n'; - add_line(minimum.line, minimum.config); - } -} - diff --git a/calcideal.cc b/calcideal.cc deleted file mode 100644 index 8099e0e4c7..0000000000 --- a/calcideal.cc +++ /dev/null @@ -1,65 +0,0 @@ -#include "tstream.hh" -#include "score.hh" -#include "pscore.hh" -#include "staff.hh" -#include "paper.hh" -#include "sccol.hh" -#include "debug.hh" - - -void -Score::do_connect(PCol *c1, PCol *c2, Real d) -{ - Idealspacing*sp=pscore_->get_spacing(c1,c2); - - if (!sp->hooke){ - sp->hooke = 1.0; - sp->space =d; - } -} - -void -Score::connect_nonmus(PCol* c1, PCol *c2, Real d) -{ - if (c2->used && c1->used) { - do_connect(c1,c2,d); - - // alert! this is broken! - if (c1->breakable()) { - do_connect(c1->postbreak, c2,d); - } - if (c2->breakable()) { - do_connect(c1, c2->prebreak,d); - } - if (c1->breakable() &&c2->breakable()) { - do_connect(c1->postbreak, c2->prebreak,d); - } - } -} -/* this needs A LOT of rethinking. - - generate springs between columns. - */ -void -Score::calc_idealspacing() -{ - PCursor sc(cols_); - - for (; sc.ok(); sc++) { - if (sc->musical) - for (int i=0; i < sc->durations.sz(); i++) { - Real d = sc->durations[i]; - 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; - connect_nonmus(sc->pcol, c2, dist); - } - else if (sc->used()) { // ignore empty columns - PCol * c2 = find_col(sc->when,true)->pcol; - connect_nonmus(sc->pcol,c2,0.0); - } - } -} - - diff --git a/command.cc b/command.cc deleted file mode 100644 index 23edf1ec36..0000000000 --- a/command.cc +++ /dev/null @@ -1,39 +0,0 @@ -#include "string.hh" -#include "debug.hh" -#include "command.hh" - -bool -Command::isbreak()const -{ - return (code >= BREAK_PRE && code <= BREAK_END); -} - -Command::Command() -{ - code = NOP; - when = -1; - priority=0; -} - - - -Command::Command(Real w) -{ - code = NOP; - when = w; - priority=0; -} - -void -Command::print() const -{ -#ifndef NPRINT - mtor << "command at " << when << ", code " << code << " prio " << priority; - if (args.sz()) { - mtor<< " args: "; - for (int i = 0; i args; - int priority; - - /****************/ - - Command(); - Command(Real w); - bool isbreak()const; - void print() const; -}; - -/** - A nonrhythmical "thing" in a staff is called a "command". - Commands have these properties: - - \begin{itemize} - \item They are \bf{not} rhythmical, i.e. they do not have a duration - \item They have a staff-wide impact, i.e. a command cannot be targeted at - only one voice in the staff: two voices sharing a staff can't have - different clefs - \item Commands are ordered, that is, when from musical point of view the - commands happen simultaneously, the order in which Staff receives the - commands can still make a difference in the output - \item Some commands are actually score wide, so Score has to issue these - commands to the Staff, eg. BREAK commands - \end{itemize} - - At this moment we have three classes of commands: - \begin{description} - INTERPRET commands are not grouped. - \item[TYPESET] These commands instruct the Staff to - typeset symbols on the output, eg meter/clef/key changes - \item[INTERPRET] These commands do not produce output, instead, - they change the interpretation of other commands or requests. - example: shift output vertically, set the key. - \item[BREAK_XXX] These commands group TYPESET commands in - prebreak and postbreak commands. \See{Col}. - Staff can insert additional commands in a sequence of BREAK_XXX - commands, eg. key change commands - - \end{description} - - These commands are generated by Score, since they have to be the - same for the whole score. - - - \begin{description} - \item[BREAK_PRE] - \item[BREAK_MIDDLE] - \item[BREAK_POST] - \item[BREAK_END] - \item[TYPESET] METER,BAR - \end{description} - - - Commands can be freely copied, they do not have virtual methods. - */ - - -#endif diff --git a/const.hh b/const.hh deleted file mode 100644 index dce593b4a0..0000000000 --- a/const.hh +++ /dev/null @@ -1,12 +0,0 @@ -/* - global constants - */ -#ifndef CONST_HH -#define CONST_HH -#include -#include "real.hh" - -const Real EPS=1e-7; // qlpsolve.hh -const int MAXITER=100; // qlpsolve.hh -const Real INFTY=HUGE; -#endif diff --git a/debug.cc b/debug.cc deleted file mode 100644 index d55c901945..0000000000 --- a/debug.cc +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include "debug.hh" -#include "dstream.hh" -#include "vector.hh" - -Dstream monitor(&cout,".dstreamrc"); -ostream * nulldev = new ofstream("/dev/null"); - - -/* - want to do a stacktrace . - */ -void -mynewhandler() -{ - cerr << "Out of free store memory. Aborting.. "<< flush; - assert(false); -} - - -void -debug_init() -{ - set_new_handler(&mynewhandler); - set_matrix_debug(monitor); -} diff --git a/debug.hh b/debug.hh deleted file mode 100644 index fb3a070593..0000000000 --- a/debug.hh +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef DEBUG_HH -#define DEBUG_HH -#include -#include -#include "dstream.hh" - -void error(String s); // errors - -// warnings -void warning(String s); -#define WARN warnout << "warning: "<<__FUNCTION__ << "(): " -extern ostream &warnout ; - -// progress -extern ostream *mlog; - -// debugging -extern Dstream monitor; // monitor - -#ifdef NPRINT -#define mtor if (0) monitor // clever hack -#else -#define mtor monitor.identify_as(__PRETTY_FUNCTION__) -#endif - - - -#endif diff --git a/dimen.cc b/dimen.cc deleted file mode 100644 index eb53756b45..0000000000 --- a/dimen.cc +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include "dimen.hh" -#include "debug.hh" -#include "string.hh" - -Real -parse_dimen(String dim) -{ - int i=dim.len()-1; - const char *s = dim; - while (i > 0 && (isspace(s[i]) || isalpha(s[i])) ){ - i--; - } - String unit(s + i+1); - return convert_dimen(dim.fvalue(), unit); -} - -const Real CM_TO_PT=72/2.54; - -Real -convert_dimen(Real quant, String unit) -{ - if (unit == "cm") - return quant * CM_TO_PT; - if (unit == "pt") - return quant; - if (unit == "mm") - return quant*CM_TO_PT/10; - if (unit == "in") - return quant * 72; - error ("unknown length unit: `" + unit+"'"); -} - -String -print_dimen(Real r) -{ - String s(r); - s += "pt "; - return s; -} diff --git a/dimen.hh b/dimen.hh deleted file mode 100644 index 4ee17ea140..0000000000 --- a/dimen.hh +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef DIMEN_HH -#define DIMEN_HH - -#include "real.hh" -#include "string.hh" - -Real parse_dimen(String); -Real convert_dimen(Real, String); -String print_dimen(Real); - -#endif - diff --git a/flower/Makefile b/flower/Makefile index dffea2fb37..b39b1f213d 100644 --- a/flower/Makefile +++ b/flower/Makefile @@ -1,6 +1,6 @@ MAJVER=1 MINVER=0 -PATCHLEVEL=8 +PATCHLEVEL=10 PACKAGENAME=flower VERSION=$(MAJVER).$(MINVER).$(PATCHLEVEL) @@ -13,6 +13,7 @@ include Sources.make obs=$(cc:.cc=.o) staticlib=libflower.a + $(staticlib): $(obs) $(AR) cr libflower.a $(obs) @@ -24,8 +25,10 @@ depend: Sources.make clean: rm -f $(obs) $(staticlib) + realclean: clean rm -f depend + DFILES=$(hh) $(cc) $(inl) $(templatecc) Makefile Sources.make TODO README DDIR=$(DNAME) @@ -34,6 +37,7 @@ dist: ln $(DFILES) $(DDIR)/ tar cfz $(DNAME).tar.gz $(DDIR)/* rm -rf $(DDIR)/ + TAGS: etags -CT $(inl) $(cc) $(hh) diff --git a/flower/README b/flower/README index d33c68f3df..6706447fcf 100644 --- a/flower/README +++ b/flower/README @@ -1,5 +1,7 @@ This library contains some general purpose routines which aren't -standardised yet. It was written by: +standardised libraries yet. It may be replaced by STL in time + +It was written by: Han-Wen Nienhuys diff --git a/flower/TODO b/flower/TODO index ef0ab6bac6..9d4ade3bcd 100644 --- a/flower/TODO +++ b/flower/TODO @@ -1,7 +1,5 @@ * PCursor -> Pointer_cursor / PointerCursor ? - * remove List::List(element) - * efficient copy cons for List * extend Interval diff --git a/flower/dstream.cc b/flower/dstream.cc index 8540e734cf..6cfc62eb3d 100644 --- a/flower/dstream.cc +++ b/flower/dstream.cc @@ -114,7 +114,10 @@ Dstream::Dstream(ostream *r, const char * cfg_nm ) Text_db cfg(fn); while (! cfg.eof()){ Text_record r( cfg++); - assert(r.sz() == 2); + if (r.sz() != 2) { + r.message("not enough fields in Dstream init."); + continue; + } (*silent)[r[0]] = r[1].to_bool(); } diff --git a/flower/list.cc b/flower/list.cc index ce5e366cc8..55e1e20507 100644 --- a/flower/list.cc +++ b/flower/list.cc @@ -36,7 +36,6 @@ List::OK() const template -inline List::~List() { Cursor next(*this); @@ -48,14 +47,17 @@ List::~List() } template -inline void -List::add( const T& thing, Cursor after_me ) +void +List::add( const T& thing, Cursor &after_me ) { if (!size_) { // not much choice if list is empty bottom_ = top_ = new Link( thing ); + if (!after_me.ok()) + after_me = bottom(); } else { // add at aprioprate place - Link *p = ( after_me.ok() ) ? - after_me.pointer() : bottom().pointer(); + if (!after_me.ok()) + after_me = bottom(); + Link *p =after_me.pointer(); p->add(thing); if (p == bottom_) // adjust bottom_ if necessary. bottom_ = p->next(); @@ -75,23 +77,37 @@ List::add( const T& thing, Cursor after_me ) */ template -inline void -List::insert( const T& thing, Cursor before_me ) +void +List::insert( const T& thing, Cursor &before_me ) { if (!size_) { bottom_ = top_ = new Link( thing ); + if (!before_me.ok()) + before_me = top(); + } else { - Link *p = - (before_me.ok())? - before_me.pointer() : top().pointer(); + if (!before_me.ok()) + before_me = top(); + + Link *p = before_me.pointer() ; p->insert(thing); if (p == top_) top_ = p->previous(); } - - size_++; + size_++; } + +template +void +List::concatenate(List const&s) +{ + Cursor b(bottom()); + for (Cursor c(s); c.ok(); c++) { + b.add(c); + b++; + } +} #endif diff --git a/flower/list.hh b/flower/list.hh index 1516e16642..117e1862e4 100644 --- a/flower/list.hh +++ b/flower/list.hh @@ -1,5 +1,3 @@ -// list.hh - #ifndef __LIST_HH #define __LIST_HH @@ -7,7 +5,7 @@ class ostream; template class Cursor; template class Link; -/// all purpose list +/// all-purpose doubly linked list template class List { @@ -15,11 +13,7 @@ class List List(List const&src); /// construct empty list - List(); - - /// construct list from first item. - List( const T& thing ); - + List(); virtual ~List(); Cursor bottom(); @@ -30,6 +24,10 @@ class List protected: friend class Cursor; friend class Link; + + void concatenate(List const &s); + + /// make *this empty void set_empty(); /** @@ -37,10 +35,10 @@ class List */ /// add after after_me - void add( const T& thing, Cursor after_me ); + void add( const T& thing, Cursor &after_me ); /// put thing before #before_me# - void insert( const T& thing, Cursor before_me ); + void insert( const T& thing, Cursor &before_me ); virtual void remove( Cursor me ); /** Remove link pointed to by me. diff --git a/flower/list.inl b/flower/list.inl index d71e947050..c3ee7e2948 100644 --- a/flower/list.inl +++ b/flower/list.inl @@ -18,13 +18,6 @@ List::set_empty() size_ = 0; } -template -inline -List::List( const T& thing ) -{ - set_empty(); - add( thing, Cursor( *this, bottom_ ) ); -} template inline void List::remove( Cursor me ) diff --git a/flower/pcursor.hh b/flower/pcursor.hh index 5e535300d7..c9cc53411f 100644 --- a/flower/pcursor.hh +++ b/flower/pcursor.hh @@ -24,6 +24,7 @@ struct PCursor : public Cursor { PCursor operator +( int no) const { return PCursor (Cursor::operator+(no)); } + PCursor(const PointerList & l) : Cursor (l) {} PCursor( const Cursor& cursor ) : Cursor(cursor) { } @@ -34,13 +35,17 @@ struct PCursor : public Cursor { T operator ->() const { return ptr(); } operator T() { return ptr(); } T operator *() { return ptr(); } + void add(const T& p ) { Cursor::add((void*) p); } + void insert(const T& p ) { Cursor::insert((void*) p);} private: // Cursor::operator void*; // sigh }; /** -don't create PointerList's + don't create PointerList's. + This cursor is just an interface class for Cursor. It takes care of the + appropriate type casts */ diff --git a/flower/plist.hh b/flower/plist.hh index 78df40cb17..ea2c0ecdae 100644 --- a/flower/plist.hh +++ b/flower/plist.hh @@ -16,8 +16,8 @@ class PointerList : public List public: PCursor top() { return PCursor (List::top()); } PCursor bottom() { return PCursor (List::bottom()); } - - PointerList( const T& thing ) : List( thing ) { } + void concatenate(PointerList const &s) { List::concatenate(s); } +// PointerList( const T& thing ) : List( thing ) { } PointerList() {} }; diff --git a/getcommands.cc b/getcommands.cc deleted file mode 100644 index 1f9362c59c..0000000000 --- a/getcommands.cc +++ /dev/null @@ -1,58 +0,0 @@ -#include "string.hh" -#include "parseconstruct.hh" -#include "command.hh" - -Command* -get_bar_command(Real w) -{ - Command*c = new Command; - c->when = w; - c->code = TYPESET; - c->args.add( "BAR"); - c->args.add( "|"); - c->priority = 100; - return c; -} - -Command * -get_meter_command(Real w, int n, int m) -{ - Command*c = new Command; - - c->when = w; - c->code = TYPESET; - c->args.add( "METER"); - c->args.add( n ); - c->args.add( m ); - c->priority = 50; // less than bar - return c; -} - -Command * -get_meterchange_command(int n, int m) -{ - Command*c = new Command; - - c->code = INTERPRET; - c->args.add( "METER"); - c->args.add( n ); - c->args.add( m ); - c->priority = 0; // more than bar - return c; -} - - -Command * -get_skip_command(int n, Real m) -{ - Command*c = new Command; - - c->code = INTERPRET; - c->args.add( "SKIP"); - c->args.add( n ); - c->args.add( m ); - c->priority = 0; // more than bar - return c; -} - - diff --git a/glob.hh b/glob.hh deleted file mode 100644 index 7b8bb557d4..0000000000 --- a/glob.hh +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef GLOB_HH -#define GLOB_HH -#include -#include -#include "real.hh" - -#include "proto.hh" -#include "const.hh" -#endif diff --git a/globvars.hh b/globvars.hh deleted file mode 100644 index 8b13789179..0000000000 --- a/globvars.hh +++ /dev/null @@ -1 +0,0 @@ - diff --git a/hdr/Makefile b/hdr/Makefile new file mode 100644 index 0000000000..81a8f4595c --- /dev/null +++ b/hdr/Makefile @@ -0,0 +1,8 @@ +default: + $(MAKE) -C .. + +dist: + ln Makefile $(hdr) $(DDIR)/$(HEADERDIR) + +TAGS: $(hdr) + etags -CT $(hdr) diff --git a/hdr/bar.hh b/hdr/bar.hh new file mode 100644 index 0000000000..187fadfe78 --- /dev/null +++ b/hdr/bar.hh @@ -0,0 +1,18 @@ +/* + bar.hh -- part of LilyPond + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef BAR_HH +#define BAR_HH +#include "item.hh" + +struct Bar: Item { + String type; + + Bar(String type); + void preprocess(); +}; +#endif // BAR_HH + diff --git a/hdr/beam.hh b/hdr/beam.hh new file mode 100644 index 0000000000..4cbc2ea0c2 --- /dev/null +++ b/hdr/beam.hh @@ -0,0 +1,44 @@ +/* + beam.hh -- part of LilyPond + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef BEAM_HH +#define BEAM_HH +#include "proto.hh" +#include "spanner.hh" +#include "list.hh" + +/// a beam connects multiple stems +struct Beam: public Spanner { + List stems; + Real slope; + Real left_pos; + /// -1 below heads, +1 above heads. + int dir; + + /****************/ + + virtual Interval width()const; + + Spanner *broken_at(const PCol *, const PCol *) const; + Beam(); + void add(Stem*); + void process(); + void calculate(); + void set_default_dir(); + void preprocess(); + Interval height()const; + void print() const; + + void set_stemlens(); +private: + void solve_slope(); + void brew_molecule(); +}; +/** Beam adjusts the stems its owns to make sure that they reach the + beam and that point in the correct direction */ + +#endif // BEAM_HH + diff --git a/hdr/boxes.hh b/hdr/boxes.hh new file mode 100644 index 0000000000..15beb8c372 --- /dev/null +++ b/hdr/boxes.hh @@ -0,0 +1,88 @@ +/* + some 2D geometrical concepts +*/ + +#ifndef BOXES_HH +#define BOXES_HH + +#include "textdb.hh" +#include "real.hh" +#include "vray.hh" + +/// 2d vector +struct Offset { + Real x,y; + + Offset operator+(Offset o)const { + Offset r(*this); + r+=o; + return r; + } + + Offset operator+=(Offset o) { + x+=o.x; + y+=o.y; + return *this; + } + Offset(Real ix , Real iy) { + x=ix; + y=iy; + } + Offset() { + x=0.0; + y=0.0; + } +}; + +/// a Real interval +struct Interval { + Real min, max; + + void translate(Real t) { + min += t; + max += t; + } + + void unite(Interval h) { + if (h.minmax) + 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; + } +}; + + +/// a 4-tuple of #Real#s +struct Box { + Interval x, y; + + void translate(Offset o) { + x.translate(o.x); + y.translate(o.y); + } + void unite(Box b) { + x.unite(b.x); + y.unite(b.y); + } + Box(svec ); + Box(); + Box(Interval ix, Interval iy); +}; + + +#endif diff --git a/hdr/command.hh b/hdr/command.hh new file mode 100644 index 0000000000..e13669f46c --- /dev/null +++ b/hdr/command.hh @@ -0,0 +1,86 @@ +#ifndef COMMAND_HH +#define COMMAND_HH + +#include "glob.hh" +#include "vray.hh" +#include "string.hh" + +enum Commandcode { + NOP, + INTERPRET, + TYPESET, + BREAK_PRE,BREAK_MIDDLE, BREAK_POST, BREAK_END +}; + +/// set a nonrythmical symbol +struct Command { + Commandcode code; + + Real when; + /// analogous to argv[] + svec args; + + /// + int priority; + /** in what order relative to other TYPESET commands (eg, bar + should precede meter). Highest priority first. */ + + /****************/ + + Command(); + Command(Real w); + bool isbreak()const; + void print() const; +}; + +/** + A nonrhythmical "thing" in a staff is called a "command". + Commands have these properties: + + \begin{itemize} + \item They are \bf{not} rhythmical, i.e. they do not have a duration + \item They have a staff-wide impact, i.e. a command cannot be targeted at + only one voice in the staff: two voices sharing a staff can't have + different clefs + \item Commands are ordered, that is, when from musical point of view the + commands happen simultaneously, the order in which Staff receives the + commands can still make a difference in the output + \item Some commands are actually score wide, so Score has to issue these + commands to the Staff, eg. BREAK commands + \end{itemize} + + At this moment we have three classes of commands: + \begin{description} + INTERPRET commands are not grouped. + \item[TYPESET] These commands instruct the Staff to + typeset symbols on the output, eg meter/clef/key changes + \item[INTERPRET] These commands do not produce output, instead, + they change the interpretation of other commands or requests. + example: shift output vertically, set the key. + \item[BREAK_XXX] These commands group TYPESET commands in + prebreak and postbreak commands. See Documentation/breaking + + Staff can insert additional commands in a sequence of BREAK_XXX + commands, eg. key change commands + + \end{description} + + These commands are generated by Score, since they have to be the + same for the whole score. + + + \begin{description} + \item[BREAK_PRE] + \item[BREAK_MIDDLE] + \item[BREAK_POST] + \item[BREAK_END] + \item[TYPESET] METER,BAR + \end{description} + + + Commands can be freely copied, they do not have virtual methods. + + */ + + +#endif diff --git a/hdr/const.hh b/hdr/const.hh new file mode 100644 index 0000000000..dce593b4a0 --- /dev/null +++ b/hdr/const.hh @@ -0,0 +1,12 @@ +/* + global constants + */ +#ifndef CONST_HH +#define CONST_HH +#include +#include "real.hh" + +const Real EPS=1e-7; // qlpsolve.hh +const int MAXITER=100; // qlpsolve.hh +const Real INFTY=HUGE; +#endif diff --git a/hdr/debug.hh b/hdr/debug.hh new file mode 100644 index 0000000000..fb3a070593 --- /dev/null +++ b/hdr/debug.hh @@ -0,0 +1,28 @@ +#ifndef DEBUG_HH +#define DEBUG_HH +#include +#include +#include "dstream.hh" + +void error(String s); // errors + +// warnings +void warning(String s); +#define WARN warnout << "warning: "<<__FUNCTION__ << "(): " +extern ostream &warnout ; + +// progress +extern ostream *mlog; + +// debugging +extern Dstream monitor; // monitor + +#ifdef NPRINT +#define mtor if (0) monitor // clever hack +#else +#define mtor monitor.identify_as(__PRETTY_FUNCTION__) +#endif + + + +#endif diff --git a/hdr/dimen.hh b/hdr/dimen.hh new file mode 100644 index 0000000000..4ee17ea140 --- /dev/null +++ b/hdr/dimen.hh @@ -0,0 +1,12 @@ +#ifndef DIMEN_HH +#define DIMEN_HH + +#include "real.hh" +#include "string.hh" + +Real parse_dimen(String); +Real convert_dimen(Real, String); +String print_dimen(Real); + +#endif + diff --git a/hdr/glob.hh b/hdr/glob.hh new file mode 100644 index 0000000000..7b8bb557d4 --- /dev/null +++ b/hdr/glob.hh @@ -0,0 +1,9 @@ +#ifndef GLOB_HH +#define GLOB_HH +#include +#include +#include "real.hh" + +#include "proto.hh" +#include "const.hh" +#endif diff --git a/hdr/globvars.hh b/hdr/globvars.hh new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/hdr/globvars.hh @@ -0,0 +1 @@ + diff --git a/hdr/identifier.hh b/hdr/identifier.hh new file mode 100644 index 0000000000..9cb80386c0 --- /dev/null +++ b/hdr/identifier.hh @@ -0,0 +1,36 @@ + +/* + identifier.hh -- part of LilyPond + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef IDENTIFIER_HH +#define IDENTIFIER_HH +#include "proto.hh" +#include "string.hh" + +struct Identifier +{ + void *data; + String name; + + Identifier(String n) ; + virtual ~Identifier(); + virtual Staff * staff() { assert(false); } + virtual Voice * voice() { assert(false); } +}; + +struct Staff_id : Identifier { + Staff_id(String s, Staff*st):Identifier(s) { data = st; } + virtual Staff* staff() { return (Staff*) data; } + ~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 + diff --git a/hdr/item.hh b/hdr/item.hh new file mode 100644 index 0000000000..33b60831c1 --- /dev/null +++ b/hdr/item.hh @@ -0,0 +1,56 @@ +#ifndef ITEM_HH +#define ITEM_HH + +#include "glob.hh" +#include "boxes.hh" +#include "string.hh" + +/// a horizontally fixed size element of the score +struct Item { + /// indirection to the column it is in + PCol * pcol_; + + /// indirection to the pstaff it is in + PStaff *pstaff_; + + /// member: the symbols + Molecule *output; + + /// + Offset offset_; + /** + This is needed, because #output# may still be + NULL. + */ + /****************/ + + void translate(Offset); + + /// 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 ; + Item(); + void print()const; + virtual ~Item(); + Paperdef *paper() const; +}; +/** 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. + +*/ + + +#endif diff --git a/hdr/keyword.hh b/hdr/keyword.hh new file mode 100644 index 0000000000..df4547ad76 --- /dev/null +++ b/hdr/keyword.hh @@ -0,0 +1,14 @@ +/* for the keyword table */ +struct Keyword_ent +{ + const char *name; + int tokcode; +}; + +struct Keyword_table +{ + Keyword_ent *table; + int maxkey; + Keyword_table(Keyword_ent *); + int lookup(const char *s) const; +}; diff --git a/hdr/leastsquares.hh b/hdr/leastsquares.hh new file mode 100644 index 0000000000..71586d8d5c --- /dev/null +++ b/hdr/leastsquares.hh @@ -0,0 +1,19 @@ +/* + leastsquare.hh -- part of LilyPond + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef LEASTSQUARE_HH +#define LEASTSQUARE_HH +#include "vray.hh" +#include "boxes.hh" + +struct Least_squares { + svec input; + void minimise(Real &coef, Real &offset); +}; + + +#endif // LEASTSQUARE_HH + diff --git a/hdr/lexer.hh b/hdr/lexer.hh new file mode 100644 index 0000000000..e2537da410 --- /dev/null +++ b/hdr/lexer.hh @@ -0,0 +1,17 @@ +#ifndef LEXER_HH +#define LEXER_HH + +#include "proto.hh" + +void new_input(String s); +bool close_input(); +int yylex(); +void yyerror(const char *s); + +int lookup_keyword(String s); + +Identifier* lookup_identifier(String s); +void add_identifier(Identifier*i); +void delete_identifiers(); +void kill_lexer(); +#endif diff --git a/hdr/linespace.hh b/hdr/linespace.hh new file mode 100644 index 0000000000..54704508e6 --- /dev/null +++ b/hdr/linespace.hh @@ -0,0 +1,95 @@ +#ifndef PROBLEM_HH +#define PROBLEM_HH + +#include "glob.hh" +#include "plist.hh" +#include "vray.hh" +#include "pcol.hh" +#include "matrix.hh" + +/// helper struct for #Spacing_problem# +struct Colinfo { + const PCol *pcol_; + bool fixed; + Real fixpos; + Colinfo(); + void print() const; + Real minright() const { return pcol_->width().max; } + Real minleft() const { return -pcol_->width().min; } +}; + + +/// spacing for one line. +class Spacing_problem { + svec ideals; + svec cols; + + /// the index of #c# in #cols# + int col_id(const PCol *c) const; + + /// generate an (nonoptimal) solution + Vector find_initial_solution() const; + + /// check if problem is too tight + bool check_feasible() const; + /// does #this# contain the column #w#? + bool contains(const PCol *w); + + /// make the energy function + void make_matrices(Matrix &quad, Vector &lin,Real&) const; + + /// generate the LP constraints + void make_constraints(Mixed_qp& lp) const; + +public: + /// solve the spacing problem + svec solve() const; + /** + return the column positions, and the energy (last element) + */ + /// add a idealspacing to the problem. + void add_ideal(const Idealspacing *i); + + /** + One pair of columns can have no, one or more idealspacings, + since they can be "summed" if the columns to which #i# refers are + not in this problem, the spacing is ignored. + */ + + + /// add a col to the problem + void add_column(const PCol *, bool fixed=false, Real fixpos=0.0); + /** columns have to be added left to right. The column contains + info on it's minimum width. + */ + + + bool check_constraints(Vector v) const; + + Vector try_initial_solution() const; + void OK() const; + void print() const; + void print_ideal(const Idealspacing*)const; +}; + + +/** the problem, given by the columns (which include constraints) and + intercolumn spacing. The problem is: + + Generate a spacing which + \begin{itemize} + \item + Satisfies spacing constraints (notes can't be printed through each other) + \item + Looks good, ie tries to conform to an ideal spacing as much as possible. + \end{itemize} + This is converted by regarding idealspacing as "springs" attached + to columns. The equilibrium of one spring is the ideal + distance. The columns have a size, this imposes "hard" constraints + on the distances. This transforms the problem into a quadratic + programming problem with linear constraints. + + The quality is given by the total potential energy in the + springs. The lower the energy, the better the configuration. +*/ +#endif diff --git a/hdr/linestaff.hh b/hdr/linestaff.hh new file mode 100644 index 0000000000..891269dd9d --- /dev/null +++ b/hdr/linestaff.hh @@ -0,0 +1,11 @@ +#include "pstaff.hh" + +struct Linestaff : PStaff { + + int nolines; + +/****************/ + + Symbol get_stafsym(Real width)const; + Linestaff(int, PScore*); +}; diff --git a/hdr/lookup.hh b/hdr/lookup.hh new file mode 100644 index 0000000000..6bf89c0093 --- /dev/null +++ b/hdr/lookup.hh @@ -0,0 +1,40 @@ +/* + lilypond, (c) 1996 Han-Wen Nienhuys +*/ +#ifndef LOOKUPSYMS_HH +#define LOOKUPSYMS_HH + +#include "symbol.hh" + +struct Lookup { + Symtables *symtables_; + + /****************/ + + void parse (Text_db&t); + Parametric_symbol *linestaff(int n); + Parametric_symbol *meter(String); + Parametric_symbol *stem(); + + Symbol beam_element(int,int,Real=0); + /// round slope to closest TeXslope + Symbol beam(Real&,Real); + Symbol streepjes(int pos); + /** + pos == 3 : 3 lines above staff (extending below note) + + pos == -3: below staff + */ + + Symbol rule_symbol(Real height, Real width); + + Symbol ball(int); + Symbol flag(int); + Symbol rest(int); + Symbol bar(String); + Symbol dots(int); + Lookup(); + ~Lookup(); +}; + +#endif diff --git a/hdr/main.hh b/hdr/main.hh new file mode 100644 index 0000000000..58928f5142 --- /dev/null +++ b/hdr/main.hh @@ -0,0 +1,11 @@ +#ifndef MAIN_HH +#define MAIN_HH +#include "proto.hh" + +void debug_init(); +void do_scores(); +void add_score(Score * s); +void set_default_output(String s); +const char *get_version(); + +#endif diff --git a/hdr/melodicstaff.hh b/hdr/melodicstaff.hh new file mode 100644 index 0000000000..b447102de6 --- /dev/null +++ b/hdr/melodicstaff.hh @@ -0,0 +1,27 @@ +/* + rhythmstaf.hh -- part of LilyPond + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef MELODICSTAFF_HH +#define MELODICSTAFF_HH + +#include "simplestaff.hh" + +/// five line staff, no multiple voices +struct Melodic_staff : public Simple_staff +{ + + /****************/ + + virtual void set_output(PScore *); + virtual Melodic_staff*clone()const; + + virtual Stem * get_stem(Stem_req *rq); + virtual Notehead * get_notehead(Note_req *rq); +}; + +#endif // MELODICSTAFF_HH + + diff --git a/hdr/meter.hh b/hdr/meter.hh new file mode 100644 index 0000000000..6af8817265 --- /dev/null +++ b/hdr/meter.hh @@ -0,0 +1,18 @@ +/* + meter.hh -- part of LilyPond + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef METER_HH +#define METER_HH +#include "item.hh" + +struct Meter: Item { + svec args; + + Meter(svec args) ; + void preprocess(); +}; +#endif // METER_HH + diff --git a/hdr/misc.hh b/hdr/misc.hh new file mode 100644 index 0000000000..64c8ca4102 --- /dev/null +++ b/hdr/misc.hh @@ -0,0 +1,7 @@ +#ifndef MISC_HH +#define MISC_HH + + + + +#endif diff --git a/hdr/molecule.hh b/hdr/molecule.hh new file mode 100644 index 0000000000..0c69f74040 --- /dev/null +++ b/hdr/molecule.hh @@ -0,0 +1,52 @@ +#ifndef MOLECULE_HH +#define MOLECULE_HH + +#include "plist.hh" +#include "boxes.hh" +#include "item.hh" +#include "symbol.hh" +/// a symbol which can be translated, and freely copied +struct Atom { + Offset off; + Symbol sym; + + void translate(Offset o) { + off += o; + } + + /// how big is #this#? + Box extent() const; + Atom(Symbol s); + + void print() const; + + String TeXstring() const; +}; + +/// a group of #Atom#s +struct Molecule { + PointerList ats; + + Molecule() { } + Molecule(Atom a) { add(a) ; } + + void add_right(const Molecule &m); + void add_left(const Molecule &m); + void add_top(const Molecule &m); + void add_bot(const Molecule &m); + void add(Molecule const &m); + void translate(Offset); + void add(Atom a) { ats.bottom().add(new Atom(a)); } + /// how big is #this#? + Box extent() const; + + String TeXstring() const; + + Molecule(const Molecule&s); + void print() const; +private: + void operator=(const Molecule&); +}; +/** a group of individually translated symbols. You can add molecules + to the top, to the right, etc. */ +#endif diff --git a/hdr/notehead.hh b/hdr/notehead.hh new file mode 100644 index 0000000000..b694e95af8 --- /dev/null +++ b/hdr/notehead.hh @@ -0,0 +1,38 @@ +/* + 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 + diff --git a/hdr/notename.hh b/hdr/notename.hh new file mode 100644 index 0000000000..ef04a0da7c --- /dev/null +++ b/hdr/notename.hh @@ -0,0 +1,2 @@ + +void lookup_notename(int &large, int &small, String s); diff --git a/hdr/paper.hh b/hdr/paper.hh new file mode 100644 index 0000000000..84932a36ab --- /dev/null +++ b/hdr/paper.hh @@ -0,0 +1,33 @@ +#include "proto.hh" +#include "real.hh" +#include "string.hh" + +/// symbols, dimensions and constants +struct Paperdef { + Lookup *lookup_; + String outfile; + Real linewidth; + + /// how much space does a whole note take (ideally?) + Real whole_width; + + /// ideal = geometric_ ^ log2(duration) + Real geometric_; + + /****************/ + void parse(); + Paperdef(); + ~Paperdef(); + Real interline()const; + Real rule_thickness()const; + Real standard_height()const; + Real note_width() const; + void print() const; + Real duration_to_dist(Real); +}; +/** This struct takes care of all kinds of symbols, dimensions and + constants. Most of them are related to the point-size of the fonts, + so therefore, the lookup table for symbols is also in here. + + see TODO + */ diff --git a/hdr/parseconstruct.hh b/hdr/parseconstruct.hh new file mode 100644 index 0000000000..259303e1a8 --- /dev/null +++ b/hdr/parseconstruct.hh @@ -0,0 +1,17 @@ +#include "proto.hh" + +template +struct svec; + +void set_default_duration(String); +void set_default_pitch(String); +Staff * get_new_rhythmstaff(); +Voice_element * get_note_element(String,String); +Voice_element* get_rest_element(String,String); +Command * get_bar_command(Real); +Staff * get_new_melodicstaff(); +Command* get_meterchange_command( int,int); +Command* get_meter_command( Real,int,int); +Command* get_skip_command( int,Real); +Request* get_request(char); +void add_requests( Voice_element*v, svec&req); diff --git a/hdr/pcol.hh b/hdr/pcol.hh new file mode 100644 index 0000000000..fa9516edb4 --- /dev/null +++ b/hdr/pcol.hh @@ -0,0 +1,95 @@ +#ifndef COLS_HH +#define COLS_HH + +#include "glob.hh" +#include "boxes.hh" +#include "plist.hh" +#include "item.hh" + +/// stuff grouped vertically. +struct PCol { + List its; + List stoppers, starters; + + /// Can this be broken? true eg. for bars. + bool breakable()const; + + /// does this column have items, does it have spacings attached? + bool used; + + /// prebreak is put before end of line. + PCol *prebreak; + /** + if broken here, then (*this) column is discarded, and prebreak + is put at end of line, owned by Col + */ + + /// postbreak at beginning of the new line + PCol *postbreak; + /** \See{prebreak} + */ + PCol *daddy; + /* + if this column is pre or postbreak, then this field points to the parent. + */ + /// if lines are broken then this column is in #line# + const Line_of_score *line; + + /// if lines are broken then this column x-coord #hpos# + Real hpos; + + + /****************************************************************/ + + void add(Item*i); + + Interval width() const; + ~PCol(); + PCol(PCol * parent); + + /// which col comes first? + static int compare(const PCol &c1, const PCol &c2); + /** + signed compare on columns. + + return < 0 if c1 < c2. + */ + + void OK() const; + void set_breakable(); + void print()const; +}; +/** + This is a class to address items vertically. It contains the data for: + \begin{itemize} + \item + unbroken score + \item + broken score + \item + the linespacing problem + \end{itemize} + */ + +#include "compare.hh" +instantiate_compare(const PCol &, PCol::compare); + + +/// ideal spacing between two columns +struct Idealspacing { + + /// the ideal distance + Real space; + + /// Hooke's constant: how strong are the "springs" attached to columns + Real hooke; + + /// the two columns + const PCol *left, *right; + + void print()const; + void OK() const ; + Idealspacing(const PCol *left,const PCol *right); +}; + +#endif diff --git a/hdr/proto.hh b/hdr/proto.hh new file mode 100644 index 0000000000..d674ca429a --- /dev/null +++ b/hdr/proto.hh @@ -0,0 +1,93 @@ +/* + proto.hh -- part of LilyPond + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef PROTO_HH +#define PROTO_HH +#include "real.hh" + +class Line_of_score; +class Line_of_staff; +class PCol; +class PStaff; +class Staff; +class Staff_column; +class Score; +class Score_column; +class Voice; +class Voice_element; +class Voicegroup; +class Request; +class Command; +class Request; +class Stem_req; +class Span_req; +class Slur_req; +class Decresc_req; +class Cresc_req; +class Bracket_req; +class Script_req; +class Rest_req; +class Note_req; +class Lyric_req; +class Chord; +class Absdynamic_req; +struct Offset; +struct Interval; +struct Box; +struct PCol; +struct Idealspacing; +struct Spanner; +struct Item; +struct Line_of_staff; +struct Colinfo; +struct Linestaff; +struct Atom; +struct Molecule; +struct PScore; +struct Request; +struct Note_req; +struct Lyric_req; +struct Script_req; +struct Rest_req; +struct Rhythmic_req; +struct Chord; +struct Stem_req; +struct Span_req; +struct Beam_req; +struct Bracket_req; +struct Slur_req; +struct Dynamic; +struct Cresc_req; +struct Decresc_req; +struct Absdynamic_req; +struct Score_column; +struct Score; +struct Staff_column; +struct Staff; +struct Command; +struct Symbol; +struct Output; +struct Text_gob; +struct Voice; +struct Voicegroup; +struct Voice_element; +struct String; +struct Tex_stream; +struct Identifier; +struct Keyword; +class Mixed_qp; +class Paperdef; +class Score_commands; +class Parametric_symbol; +struct Lookup; +struct Symtables; +struct Symtable; +struct Stem; +struct Notehead; +struct Beam; +struct Rest; +#endif // PROTO_HH + diff --git a/hdr/pscore.hh b/hdr/pscore.hh new file mode 100644 index 0000000000..70e783c889 --- /dev/null +++ b/hdr/pscore.hh @@ -0,0 +1,102 @@ +// the breaking problem for a score. + +#ifndef PSCORE_HH +#define PSCORE_HH + + +#include "vray.hh" +#include "pcol.hh" +#include "pstaff.hh" + +/// all stuff which goes onto paper +struct PScore { + Paperdef *paper_; // indirection. + + /// the columns, ordered left to right + PointerList cols; + + /// the idealspacings, no particular order + PointerList suz; + + /// the staffs ordered top to bottom + PointerList staffs; + + /// all symbols in score. No particular order. + PointerList its; + + /// if broken, the different lines + PointerList lines; + + /// crescs etc; no particular order + PointerList spanners; + + /****************************************************************/ + + svec select_items(PStaff*, PCol*); + + /// before calc_breaking + void preprocess(); + + void calc_breaking(); + /** + calculate where the lines are to be broken. + + POST + + lines contain the broken lines. + */ + + /// after calc_breaking + void postprocess(); + + /// search all pcols which are breakable. + svec find_breaks() const; + + /// add a line to the broken stuff. Positions given in #config# + void add_line(svec curline, svec config); + + /// helper: solve for the columns in #curline#. + svec solve_line(svec curline) const; + + void add(PStaff *); + /// add item + void typeset_item(Item *, PCol *,PStaff*,int=1); + + /// add an Spanner + void typeset_spanner(Spanner*, PStaff*); + + /// add to bottom of pcols + void add(PCol*); + /** + + */ + void output(Tex_stream &ts); + + Idealspacing* get_spacing(PCol *, PCol *); + /* + get the spacing between c1 and c2, create one if necessary. + */ + + /// return argument as a cursor. + PCursor find_col(PCol *); + + /// delete unused columns + void clean_cols(); + + + /// check if the spacing/breaking problem is well-stated + void problem_OK() const; + + /// invarinants + void OK()const; + PScore(Paperdef*); + void print() const; + + /// does curline fit on the paper? + bool feasible(svec curline) const; +}; +/** notes, signs, symbols in a score can be grouped in two ways: + horizontally (staffwise), and vertically (columns). #PScore# + contains the items, the columns and the staffs. + */ +#endif diff --git a/hdr/pstaff.hh b/hdr/pstaff.hh new file mode 100644 index 0000000000..bf33c6b437 --- /dev/null +++ b/hdr/pstaff.hh @@ -0,0 +1,23 @@ +#ifndef PSTAFF_HH +#define PSTAFF_HH + +#include "plist.hh" +#include "item.hh" +#include "symbol.hh" + +/// items grouped vertically. +struct PStaff { + Parametric_symbol *stafsym; + PScore * pscore_; + + virtual Symbol get_stafsym(Real width)const=0; // maybe overkill + + List spans; + List its; + + void add(Item*i); + PStaff(PScore*); + virtual ~PStaff() {} +}; + +#endif diff --git a/hdr/qlp.hh b/hdr/qlp.hh new file mode 100644 index 0000000000..b539fe6b86 --- /dev/null +++ b/hdr/qlp.hh @@ -0,0 +1,89 @@ +#ifndef QLP_HH +#define QLP_HH + +#include "matrix.hh" + +/// inequality constrained quadratic program +class Ineq_constrained_qp { + friend class Active_constraints; + + svec cons; + svec consrhs; +public: + Matrix quad; + Vector lin; + Real const_term; + + /// + void assert_solution(Vector sol) const; + /** + use a KKT method to assert optimality of sol + */ + /// solve the problem using a projected gradient method + Vector solve(Vector start) const; + + int dim() const{ + return lin.dim(); + } + /** return the number of variables in the problem */ + /// + void add_inequality_cons(Vector c, double r); + /** + add a constraint + + + c*vars >= r + + PRE + c.dim() == dim(); + + */ + /// + Ineq_constrained_qp(int novars); + /** set up matrices to go with the problem. */ + + Real eval(Vector v); + /** + evaluate the quadratic function for input #v# + */ + + void eliminate_var(int idx, Real value); + void OK()const; + void print() const; + +}; + +/// Quadratic programming with mixed linear constraints +class Mixed_qp :public Ineq_constrained_qp { + svec eq_cons; + svec eq_consrhs; +public: + Mixed_qp(int n); + void OK() const; + void print() const; + + Vector solve(Vector start) const; + void add_fixed_var(int i , Real value); + + /// + void add_equality_cons(Vector c, double r); + /** + add a constraint, + + c*vars == r + + PRE + c.dim()==dim(); + */ + +}; +/** + problem definition of a quadratic optimisation problem with linear + inequality and equality constraints + + + x^T QUAD x /2 + b^T x +*/ + + +#endif diff --git a/hdr/qlpsolve.hh b/hdr/qlpsolve.hh new file mode 100644 index 0000000000..4d29bcc4a0 --- /dev/null +++ b/hdr/qlpsolve.hh @@ -0,0 +1,78 @@ +#include "qlp.hh" +#include "matrix.hh" + + +class Active_constraints { + friend class Inactive_iter; + + + Matrix A,H; + svec active; + svec inactive; // actually this is a set, not an array. + const Ineq_constrained_qp *opt; + +public: + String status()const; + + Vector vec(int k) const { return opt->cons[k]; } + Real rhs(int k) const { return opt->consrhs[k]; } + + /// drop constraint + void drop (int k); + /** drop constraint k from the active set. k is the index of the + constraint in #active# + + */ + + /// add constraint j + void add(int j); + /** + add constraint j to the active set j is the index of the + constraint in #inactive# + */ + + /// exchange in and out. + void exchange(int in, int out) { add(in); drop (out); } + + /// + Vector find_active_optimum(Vector g); + + /// get lagrange multipliers. + Vector get_lagrange(Vector v); + + Active_constraints(Ineq_constrained_qp const *op); + /** construct: no constraints active, n vars. Put the equalities + into the constraints. */ + + /// check invariants + void OK(); +}; + +/** + This class represents the set of active (binding) constraints + which can be active while the QLP algorithm is in a feasible + point. The active constraints are numbered. + If the constraints are of the form + + A^T*x >= b + + then the binding constraints are those where the >= is equality. + + */ + +/// +class Inactive_iter { + int j; + Active_constraints const* ac; +public: + Inactive_iter(Active_constraints const &c) { ac=&c; j=0; } + int idx() const { return j; } + void operator ++(int) { j++; } + int constraint_id() const { return ac->inactive[j]; } + Vector vec() const { return ac->vec(constraint_id()); } + Real rhs() const { return ac->rhs(constraint_id()); } + bool ok() const { return j < ac->inactive.sz(); } +}; +/** + loop through the inactive constraints. + */ diff --git a/hdr/request.hh b/hdr/request.hh new file mode 100644 index 0000000000..1911f20219 --- /dev/null +++ b/hdr/request.hh @@ -0,0 +1,237 @@ +// LilyPond's second egg of columbus! +#ifndef REQUEST_HH +#define REQUEST_HH + +#include "glob.hh" +#include "string.hh" + +/// a voice element wants something printed +struct Request { + Voice_element*elt; // indirection. + + /****************/ + + Request(); + + virtual void print()const ; + virtual Note_req *note() {return 0;} + virtual Stem_req *stem() {return 0;} + virtual Rest_req *rest() {return 0;} + virtual Span_req *span() {return 0;} + virtual Beam_req *beam() { return 0 ; } + virtual Rhythmic_req*rhythmic() { return 0;} + virtual Real duration() const { return 0.0; } + virtual Request* clone() const =0; +}; + +/** + Any Voice_element can do a number of requests. A request is done + to the #Staff# which contains the #Voice_element#. The staff decides + whether to to honor the request, ignore it, or merge it with other + requests. Merging of requests is preferably done with other + requests done by members of the same voicegroups (beams, brackets, stems) + + Please refer to the documentation of the Child classes of + #Request# for explanation of each request type. + + The result of a request will be an #Item# or a #Spanner#, which + will be put on a #PStaff#. Note that the #PStaff# and the original + #Staff# need not have anything in common. For example, the + ``double'' piano Staff could interpret commands which juggle + melodies across the left and right hand, and may put the result in + two five-line PStaffs (maybe with extra PStaffs to carry the dynamic + signs and any lyric. + + The class #Staff# should be thought as a container for the + #Voice#s, and an interpreter for #Request#s and #Command#s. + Different staffs can produce different outputs; a melodious voice + which is put into a percussion-Staff, will be typeset as the rythm of + that voice. + + After #Staff# made up her mind (Would #Staff# be a smart + name? How about #struct Susan {}# :-), the resultant items and + spanners are put on the PScore, and pointers to these items are + stored in the #Voice_element#. This construction enables the + beams/stems to look up the balls it has to connect to. */ + + +/// a request with a duration +struct Rhythmic_req : Request { + int balltype; + int dots; + + /****************/ + + Real duration() const; + Rhythmic_req(); + Rhythmic_req*rhythmic() { return this;} + void print ()const; + Request*clone() const; +}; + +/// Put a note of specified type, height, and with accidental on the staff. +struct Note_req : Rhythmic_req { + char name; + int octave; + int accidental; + bool forceacc; + + /****************/ + + // return height from central c (in halflines) + int height()const; + Note_req(); + Note_req*note() { return this;} + virtual void print() const; + Request*clone() const; +}; +/** +Staff has to decide if the ball should be hanging left or right. This +influences the horizontal dimensions of a column, and this is why +request processing should be done before horizontal spacing. + +Other voices' frivolities may cause the need for accidentals, so this +is also for the Staff to decide. The Staff can decide on positioning +based on ottava commands and the appropriate clef. +*/ + + +///Put a rest on the staff. +struct Rest_req : Rhythmic_req { + + void print()const; + + Rest_req * rest() { return this;} + Request*clone() const ; +}; +/** +Why a request? It might be a good idea to not typeset the rest, if the paper is too crowded. +*/ + +/// attach a stem to the noteball +struct Stem_req : Request { + /// 4,8,16, .. + int stem_number; + + virtual Stem_req *stem() {return this;} + Stem_req(int s) { stem_number = s; } + Request*clone() const; +}; + +/// requests to start or stop something. +struct Span_req : Request { + /// should the spanner start or stop, or is it unwanted? + enum { + NOSPAN, START, STOP + } spantype ; + + Span_req*span() { return this; } + Span_req(); + virtual Request*clone()const; +}; +/** + This type of request typically results in the creation of a #Spanner# +*/ + + +///Start / stop a beam at this note. +struct Beam_req : Span_req { + int nplet; + + /****************/ + + Beam_req(); + virtual Beam_req * beam() { return this; } + virtual Request*clone()const; +}; +/** Staff will have to combine this with the stem_request, since the + number of flags that a stem wants to carry will determine the + number of beams. if #nplet# is set, the staff will try to put an + appropriate number over the beam + + */ + +/// a slur +struct Slur_req : Span_req { + virtual Request*clone()const; +}; + + +#if 0 + +///Put a lyric above or below (?) this staff. +struct Lyric_req : Request { + String text; +}; + + +///Put a script above or below this ``note'' +struct Script_req : Request { + int orientation; + Symbol sym; +}; +/** +eg upbow, downbow. Why a request? These symbols may conflict with slurs and brackets, so this +also a request +*/ + + + + +///Draw a (Guitar) chord above or below this ``note'' +struct Chord : Request { + // don't know how this looks. +}; +/** +Why a request? +Because everything else is done in requests. +*/ + + +/// for absolute dynamics +enum Loudness { + FFF, FF, F, MF, MP, P, PP, PPP +} ; + + +///Start / stop a slur or a bracket. +struct Bracket_req : Span_req { + int nplet; +}; +/** +Start/stop a bracket at this note. if #nplet# is set, the staff will +try to put an appropriate number over the bracket +*/ + +/// helper in the hierarchy +struct Dynamic { + Real subtime; +}; +/** Each dynamic is bound to one note ( a crescendo spanning multiple + notes is thought to be made of two "dynamics": a start and a stop). + Dynamic changes can occur in a smaller time than the length of its + note, therefore fore each Dynamic request carries a time, measured + from the start of its note. + + This subfield would come in handy, if mpp96 was adapted for midi + support. + + Dynamic should have been derived from request, but I don't want to + fuss with virtual baseclasses. */ + +/// do a crescendo +struct Cresc_req : Span_req, Dynamic { + +}; + +/// do a decrescendo +struct Decresc_req : Span_req, Dynamic { + +}; + +/// do a dynamic like "fff" or "mp" +struct Absdynamic_req : Request, Dynamic { + Loudness loudness; +}; +#endif +#endif diff --git a/hdr/rest.hh b/hdr/rest.hh new file mode 100644 index 0000000000..c5d0d7f995 --- /dev/null +++ b/hdr/rest.hh @@ -0,0 +1,33 @@ +/* + rest.hh -- part of LilyPond + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef REST_HH +#define REST_HH +#include "item.hh" + +/// ball at the end of the stem +struct Rest : public Item +{ + int dots; + int balltype; + + /****************/ + + void preprocess(); + Rest(int dur,int dots); + void print()const; +private: + void brew_molecole(); +}; +/** + takes care of: + + * help lines + * proper placing of dots + + */ +#endif + diff --git a/hdr/rhythmstaff.hh b/hdr/rhythmstaff.hh new file mode 100644 index 0000000000..46c35107d2 --- /dev/null +++ b/hdr/rhythmstaff.hh @@ -0,0 +1,27 @@ +/* + rhythmstaf.hh -- part of LilyPond + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef RHYTHMSTAF_HH +#define RHYTHMSTAF_HH + +#include "simplestaff.hh" + +/// all notes on one line +struct Rhythmic_staff : public Simple_staff +{ + + /****************/ + + virtual Item *get_TYPESET_item(Command*); + virtual Stem *get_stem(Stem_req *rq); + virtual Notehead * get_notehead(Note_req *rq); + virtual void set_output(PScore *); + virtual Rhythmic_staff*clone()const; +}; + +#endif // RHYTHMSTAF_HH + + diff --git a/hdr/sccol.hh b/hdr/sccol.hh new file mode 100644 index 0000000000..f18b659e7e --- /dev/null +++ b/hdr/sccol.hh @@ -0,0 +1,49 @@ +/* + sccol.hh -- part of LilyPond + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef SCCOL_HH +#define SCCOL_HH +#include "pcol.hh" + + +struct Score_column { + + /// indirection to column + PCol * pcol; + /// length of notes/rests in this column + svec durations; + + Real when; + + /// + bool musical; + + /****************/ + + Score_column(Real when); + static int compare(Score_column & c1, Score_column &c2) { + return sgn(c1.when - c2.when); + } + void set_breakable() { + pcol->set_breakable(); + } + bool used(); + void print() const; +}; +/** + + When typesetting hasn't started on PScore yet, the columns which + contain data have a rhythmical position. Score_column is the type + with a rhythmical time attached to it. The calculation of + idealspacing is done with data in these columns. (notably: the + #durations# field) + + */ + +instantiate_compare(Score_column&, Score_column::compare); + +#endif // SCCOL_HH + diff --git a/hdr/scommands.hh b/hdr/scommands.hh new file mode 100644 index 0000000000..ae908d7647 --- /dev/null +++ b/hdr/scommands.hh @@ -0,0 +1,39 @@ +/* + lilypond, (c) 1996 Han-Wen Nienhuys +*/ +#ifndef SCOMMANDS_HH +#define SCOMMANDS_HH + +#include "proto.hh" +#include "command.hh" +#include "vray.hh" +#include "plist.hh" + +/// the list of commands in Score +struct Score_commands : public PointerList { + void process_add(Command); + Score_commands*parse(Real last)const; + void parser_add(Command*); + void add_seq(svec); + void clean(Real last); + void set_breakable(Real when); + bool is_breakable(Real w); + PCursor last_insertion(Real w); + PCursor first(Real w); + void add_command_to_break(Command pre, Command mid,Command post); + void OK() const; + void print() const; + Real last() const; + void insert_between(Command victim, PCursor firstc, + PCursor last); +}; +/** the list of commands in Score. Put in a separate class, since it + otherwise clutters the methods of Score. + + This class serves two purposes: it stores the commands (via + parser_add()) in the yacc parser. at a later stage, some 'high + level' commands are converted (method: parse()) + */ + +#endif + diff --git a/hdr/score.hh b/hdr/score.hh new file mode 100644 index 0000000000..176d7fa47a --- /dev/null +++ b/hdr/score.hh @@ -0,0 +1,52 @@ +#ifndef SCORE_HH +#define SCORE_HH +#include "vray.hh" +#include "proto.hh" +#include "plist.hh" + + +/// the total music def of one movement +struct Score { + /// paper_, staffs_ and commands_ form the problem definition. + Paperdef *paper_; + PointerList staffs_; + Score_commands *commands_; + + /// "runtime" fields for setting up spacing + PointerList cols_; + PScore *pscore_; + + /****************************************************************/ + + /// construction + void add_staff(Staff *st); + void set(Paperdef*); + Score(); + ~Score(); + void add(Staff*); + void set(Score_commands*); + + + void OK() const; + Score_column *find_col(Real,bool); + void process(); + void output(String fn); + PCursor create_cols(Real); + void print() const; + Real last() const; + +private: + void do_pcols(); + void clean_cols(); + void distribute_commands(); + void do_connect(PCol *c1, PCol *c2, Real d); + void connect_nonmus(PCol* c1, PCol *c2, Real d); + /// add #Idealspacings# to #pscore_# + void calc_idealspacing(); + /** add the score wide commands (bars, breaks) to each staff so + they can process (typeset) them if needed */ +}; +/** + + */ +#endif diff --git a/hdr/scoreline.hh b/hdr/scoreline.hh new file mode 100644 index 0000000000..3da47d30dc --- /dev/null +++ b/hdr/scoreline.hh @@ -0,0 +1,32 @@ +/* + scoreline.hh -- part of LilyPond + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef SCORELINE_HH +#define SCORELINE_HH +#include "plist.hh" +#include "proto.hh" +#include "vray.hh" + +/// the columns of a score that form one line. +struct +Line_of_score { + List cols; + + // need to store height of each staff. + PointerList staffs; + const PScore * score; // needed to generate staffs + + /****************/ + + Line_of_score(svec sv, const PScore *); + + String TeXstring() const; + + // is #c# contained in #*this#? + bool element(const PCol *c); +}; + +#endif diff --git a/hdr/simplestaff.hh b/hdr/simplestaff.hh new file mode 100644 index 0000000000..c5c025a166 --- /dev/null +++ b/hdr/simplestaff.hh @@ -0,0 +1,79 @@ +/* + simplestaff.hh -- part of LilyPond + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef SIMPLESTAFF_HH +#define SIMPLESTAFF_HH + +#include "stcol.hh" +#include "staff.hh" +#include "swalker.hh" +/* + mega-stupido staffs and cols: they do notes one at each moment. + */ + +struct Simple_staff; + +/// column of Simple_staff: store one request +struct Simple_column : Staff_column { + + svec notes; + Stem_req *stem_; + Beam_req *beam_; + Simple_staff* staff_; + + /****************/ + + virtual void typeset_item(Item *, int=1); + + Molecule *create_command_mol(Command *com); + + void take_request(Request *rq); + virtual void process_requests(); + + Simple_column(Score_column*s,Simple_staff*rs); +}; + + +/// Simple staff: one voicegroup at a time +struct Simple_staff : Staff { + /// indirection to the PStaff. + PStaff *theline; + + /****************/ + Staff_column*create_col(Score_column*); + + virtual Item *get_TYPESET_item(Command*); + virtual Stem *get_stem(Stem_req *rq)=0; + virtual Notehead *get_notehead(Note_req *rq)=0; + virtual Rest *get_rest(Rest_req *rq); + virtual void set_output(PScore *); + + void process_commands( PCursor &where); + virtual void walk(); + + Simple_staff(); +}; + +struct Simple_walker: Staff_walker { + Stem *stem_; + svecnoteheads; + Beam *beam_; + + /****************/ + + virtual void process_command(Command*); + virtual void process_requests(); + Simple_walker(Simple_staff*); + Simple_column *col(); + Simple_staff *staff(); +}; + + +#endif // SIMPLESTAFF_HH + + + + diff --git a/hdr/spanner.hh b/hdr/spanner.hh new file mode 100644 index 0000000000..3940cebf60 --- /dev/null +++ b/hdr/spanner.hh @@ -0,0 +1,48 @@ +/* + spanner.hh -- part of LilyPond + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef SPANNER_HH +#define SPANNER_HH +#include "proto.hh" + +/// a symbol which is attached between two columns. +struct Spanner { + PCol *left, *right; + PStaff * pstaff_; + Molecule *output ; + + /****************/ + + String TeXstring () const ; + Spanner(); + Paperdef*paper() const; + + virtual Interval height()const=0; + /** + PRE: + processed + */ + virtual Interval width()const; + virtual void process(); + virtual void preprocess(); + + + /// clone a piece of this spanner. + virtual Spanner *broken_at(const PCol *c1, const PCol *c2) const=0; + /** + + PRE + c1 >= start, c2 <= stop + */ + virtual void print() const; +}; +/** Spanner should know about the items which it should consider: + e.g. slurs should be steep enough to "enclose" all those items. This + is absolutely necessary for beams, since they have to adjust the + length of stems of notes they encompass. + + */ +#endif diff --git a/hdr/staff.hh b/hdr/staff.hh new file mode 100644 index 0000000000..ee95864fa9 --- /dev/null +++ b/hdr/staff.hh @@ -0,0 +1,66 @@ +#ifndef STAFF_HH +#define STAFF_HH + +#include "score.hh" +#include "voice.hh" +#include "command.hh" + + +/// base class for a collection of voices. +struct Staff { + /// synchronous horizontal stuff + PointerList voices; + + /// commands in chronological order + PointerList commands; + + /// runtime field + PointerList cols; + + /// indirections to the Score and PScore + Score *score_; + PScore *pscore_; + + /****************************************************************/ + Staff(const Staff&src); + void add_voice(Voice *v); + void add_staff_column(Staff_column *sp); + + Paperdef*paper()const; + /// interpret all requests and add items to #destination#. + void process(); + /** + This routines calls virtual functions from Staff, to delegate the + interpretation of requests to a derived class of Staff */ + void setup_staffcols(); + + void OK() const; + void print() const; + Real last() const; + void clean_cols() ; + Staff_column * get_col(Real,bool); + + void add_commands(PointerListconst & sv); + /** + add all commands from sv. + + PRE + sv is time-ordered. + */ + + Staff(); + /** + Should construct with Score as arg, but this isn't known during parsing. + */ + /**************************************************************** + VIRTUALS + ****************************************************************/ + virtual Staff*clone()const=0; + virtual void set_output(PScore * destination)=0; + virtual void walk()=0; + virtual Staff_column * create_col(Score_column * )=0; + virtual ~Staff() { } +}; +#endif + + diff --git a/hdr/staffline.hh b/hdr/staffline.hh new file mode 100644 index 0000000000..a04078923c --- /dev/null +++ b/hdr/staffline.hh @@ -0,0 +1,29 @@ +/* + staffline.hh -- horizontal structures for broken scores. + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef STAFFLINE_HH +#define STAFFLINE_HH + +#include "real.hh" +#include "plist.hh" +#include "vray.hh" +#include "glob.hh" +#include "pstaff.hh" + +/// one broken line of staff. +struct Line_of_staff { + PointerList brokenspans; + Line_of_score const * scor; + const PStaff *pstaff_; + + /****************/ + + String TeXstring() const; + Line_of_staff(Line_of_score*, PStaff *); + Interval height() const; +}; + +#endif diff --git a/hdr/stcol.hh b/hdr/stcol.hh new file mode 100644 index 0000000000..17469a4db5 --- /dev/null +++ b/hdr/stcol.hh @@ -0,0 +1,40 @@ +/* + stcol.hh -- part of LilyPond + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef STCOL_HH +#define STCOL_HH +#include "proto.hh" +#include "vray.hh" + +/// store simultaneous requests +struct Staff_column { + /// indirection + Score_column *score_column; + + /// fields to collect data vertically. + svec v_elts; + + /// idem + svec s_commands; + + /****************/ + + Staff_column(Score_column*s); + bool mus() const; + Real when() const; + void add(Voice_element*ve); + /**************************************************************** + VIRTUAL + ****************************************************************/ + + virtual void process_requests()=0; + + virtual ~Staff_column() { } +}; + + +#endif // STCOL_HH + diff --git a/hdr/stem.hh b/hdr/stem.hh new file mode 100644 index 0000000000..6b7bc55d7d --- /dev/null +++ b/hdr/stem.hh @@ -0,0 +1,66 @@ +/* + 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 diff --git a/hdr/swalker.hh b/hdr/swalker.hh new file mode 100644 index 0000000000..c00923ff99 --- /dev/null +++ b/hdr/swalker.hh @@ -0,0 +1,34 @@ + +/* + swalker.hh -- part of LilyPond + + (c) 1996 Han-Wen Nienhuys +*/ + +#ifndef SWALKER_HH +#define SWALKER_HH + +#include "staff.hh" + +struct Staff_walker : public PCursor { + Staff * staff_; + PScore * pscore_; + + int break_status; + + /****************/ + int priority() const; // Command + Real when() const; + virtual ~Staff_walker(); + Staff_walker(Staff*, PScore*); + void process() ; + virtual void process_command(Command *)=0; + virtual void process_requests()=0; +}; +/** + manage run-time info when walking staffcolumns such as: key, + meter, pending beams & slurs + */ + +#endif // SWALKER_HH + diff --git a/hdr/symbol.hh b/hdr/symbol.hh new file mode 100644 index 0000000000..4f26e04e66 --- /dev/null +++ b/hdr/symbol.hh @@ -0,0 +1,27 @@ +#ifndef SYMBOL_HH +#define SYMBOL_HH +#include "string.hh" +#include "boxes.hh" +#include "proto.hh" + +struct Symbol { + String tex; + Box dim; + + Symbol (String, Box); + Symbol(); +}; + +struct Parametric_symbol { + Symtables*symtables_; // indirection + + /*****************/ + + Parametric_symbol(Symtables*s) { symtables_ = s; } + Symbol eval(String args1) const; // convenience + Symbol eval(String args1,String arg2) const; // convenience + virtual Symbol eval(svec args)const =0; + virtual ~Parametric_symbol(){} +}; + +#endif diff --git a/hdr/symtable.hh b/hdr/symtable.hh new file mode 100644 index 0000000000..a1443a7d3b --- /dev/null +++ b/hdr/symtable.hh @@ -0,0 +1,23 @@ +/* + lilypond, (c) 1996 Han-Wen Nienhuys +*/ +#ifndef SYMTABLE_HH +#define SYMTABLE_HH +#include "assoc.hh" +#include "string.hh" +#include "symbol.hh" + +struct Symtable : public Assoc { + Symbol lookup(String)const; +}; + + +struct Symtables : private Assoc { + void read(Text_db&) ; + Symtable* operator()(String s); + +}; + + +#endif + diff --git a/hdr/tex.hh b/hdr/tex.hh new file mode 100644 index 0000000000..546797a7c1 --- /dev/null +++ b/hdr/tex.hh @@ -0,0 +1,21 @@ +#ifndef TEX_HH +#define TEX_HH + +#include "string.hh" +#include "boxes.hh" + +/// parameter substitution in TeXstrings +String +substitute_args(String source, svec args); +/** + this structure provides a simple macro mechanism: + + if source == "tex%bla%", then + eval({"X","Y"}) == "texXblaY" + */ + +/// #h# is in points +String vstrut(Real h); + + +#endif diff --git a/hdr/tstream.hh b/hdr/tstream.hh new file mode 100644 index 0000000000..9474dd69a8 --- /dev/null +++ b/hdr/tstream.hh @@ -0,0 +1,27 @@ +#ifndef TSTREAM__HH +#define TSTREAM__HH + +#include +#include "string.hh" + +/// TeX output +struct Tex_stream { + bool outputting_comment; + ostream *os; + int nest_level; + + /// open a file for writing + Tex_stream(String filename); + void header(); + /// delegate conversion to string class. + Tex_stream &operator<<(String); + + /// close the file + ~Tex_stream(); +}; +/** + Use this class for writing to a TeX file. + It counts braces to prevent nesting errors, and + it will add a comment sign before each newline. + */ +#endif diff --git a/hdr/voice.hh b/hdr/voice.hh new file mode 100644 index 0000000000..7180ece99e --- /dev/null +++ b/hdr/voice.hh @@ -0,0 +1,53 @@ +#ifndef VOICE_HH +#define VOICE_HH + + +#include "plist.hh" +#include "request.hh" + +/// class for horizontal stuff. +struct Voice { + PointerList elts; + Real start; + + /****************/ + Real when(const Voice_element*)const; + Real last() const; + Voice(); + Voice(Voice const&); + void add(Voice_element*); + void print() const; +}; +/** + + Voice is a ordered row of Voice_elements. It is strictly horizontal: + you cannot have two rhythmic elements running parallel in a Voice + + */ + +struct Voicegroup { + /// don't know how to identify these. +}; + +/// one horizontal bit. +struct Voice_element { + Real duration; + const Voicegroup *group; + const Voice *voice; + PointerList reqs; + + List granted_items; + List granted_spanners; + + /****************/ + + void add(Request*); + Voice_element(); + Voice_element(Voice_element const & src ); + void print ()const; +}; +/** Apart from being a container for the requests, Voice_element is + glue between related items and spanners, between requests and + (voice)groups + */ +#endif diff --git a/identifier.cc b/identifier.cc deleted file mode 100644 index 5405d5f710..0000000000 --- a/identifier.cc +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include "identifier.hh" -#include "staff.hh" -#include "lexer.hh" -#include "parser.hh" - -Identifier::Identifier(String n) - :name (n) -{ - data = 0; -} - - -Identifier::~Identifier() -{ -} - -Staff_id::~Staff_id() -{ - delete staff(); -} - -Voice_id::~Voice_id() -{ - delete voice(); -} diff --git a/identifier.hh b/identifier.hh deleted file mode 100644 index 9cb80386c0..0000000000 --- a/identifier.hh +++ /dev/null @@ -1,36 +0,0 @@ - -/* - identifier.hh -- part of LilyPond - - (c) 1996 Han-Wen Nienhuys -*/ - -#ifndef IDENTIFIER_HH -#define IDENTIFIER_HH -#include "proto.hh" -#include "string.hh" - -struct Identifier -{ - void *data; - String name; - - Identifier(String n) ; - virtual ~Identifier(); - virtual Staff * staff() { assert(false); } - virtual Voice * voice() { assert(false); } -}; - -struct Staff_id : Identifier { - Staff_id(String s, Staff*st):Identifier(s) { data = st; } - virtual Staff* staff() { return (Staff*) data; } - ~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 - diff --git a/item.cc b/item.cc deleted file mode 100644 index f10187bbb2..0000000000 --- a/item.cc +++ /dev/null @@ -1,52 +0,0 @@ -#include "line.hh" -#include "symbol.hh" -#include "molecule.hh" -#include "pcol.hh" - -void -Item::postprocess() -{ - // default: do nothing -} - - -void -Item::preprocess() -{ - // default: do nothing -} - -String -Item::TeXstring() const -{ - return output->TeXstring(); -} - -Interval -Item::width() const -{ - return output->extent().x; -} - -Interval -Item::height() const -{ - return output->extent().y; -} - -Item::~Item() -{ - delete output; -} - -Item::Item() -{ - col = 0; - output = 0; - pstaff_ = 0; -} -void -Item::print() const -{ - output->print(); -} diff --git a/item.hh b/item.hh deleted file mode 100644 index b450ab59ea..0000000000 --- a/item.hh +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef ITEM_HH -#define ITEM_HH - -#include "glob.hh" -#include "boxes.hh" -#include "string.hh" - -/// a horizontally fixed size element of the score -struct Item { - const PCol * col; - Molecule *output; - - PStaff *pstaff_; - /** needed for knowing at which staff to output this 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 ; - Item(); - void print()const; - virtual ~Item(); -}; -/** 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. - -*/ - - -#endif diff --git a/keyword.cc b/keyword.cc deleted file mode 100644 index 14903cfb61..0000000000 --- a/keyword.cc +++ /dev/null @@ -1,79 +0,0 @@ -/* - keyword.cc -- keywords and identifiers - */ - -#include - -#include "glob.hh" -#include "lexer.hh" -//#include "mudobs.hh" -//#include "gram.hh" - -/* for the keyword table */ -struct Keyword_ent -{ - const char *name; - int tokcode; -}; - -struct Keyword_table -{ - Keyword_ent *table; - int maxkey; - Keyword_table(Keyword_ent *); - int lookup(const char *s) const; -}; - - -/* for qsort */ -int - tabcmp(const void * p1, const void * p2) -{ - return strcmp(((const Keyword_ent *) p1)->name, - ((const Keyword_ent *) p2)->name); -} - -Keyword_table::Keyword_table(Keyword_ent *tab) -{ - table = tab; - - /* count keywords */ - for (maxkey = 0; table[maxkey].name; maxkey++); - - /* sort them */ - qsort(table, maxkey, sizeof(Keyword_ent), tabcmp); -} - -/* - lookup with binsearch, return tokencode. -*/ -int -Keyword_table::lookup(const char *s)const -{ - int lo, - hi, - cmp, - result; - lo = 0; - hi = maxkey; - - /* binary search */ - do - { - cmp = (lo + hi) / 2; - - result = strcmp(s, table[cmp].name); - - if (result < 0) - hi = cmp; - else - lo = cmp; - } - while (hi - lo > 1); - if (!strcmp(s, table[lo].name)) - { - return table[lo].tokcode; - } else - return -1; /* not found */ -} - diff --git a/keyword.hh b/keyword.hh deleted file mode 100644 index df4547ad76..0000000000 --- a/keyword.hh +++ /dev/null @@ -1,14 +0,0 @@ -/* for the keyword table */ -struct Keyword_ent -{ - const char *name; - int tokcode; -}; - -struct Keyword_table -{ - Keyword_ent *table; - int maxkey; - Keyword_table(Keyword_ent *); - int lookup(const char *s) const; -}; diff --git a/kortjakje.ly b/kortjakje.ly new file mode 100644 index 0000000000..4c555c88eb --- /dev/null +++ b/kortjakje.ly @@ -0,0 +1,40 @@ +% "Ah, je vous dirai, maman" (Mozart) +% +% bare bones version. (written down from memory :-) + +melodie = voice { + $ \octave c + %%% theme + c c g g a a g2 f f e e d d c2 + %%% var 1 + c r8 c8 ( ) g r8 g8 ( ) a r8 a8 ( ) g r4 + f r8 f8 ( ) e4 r8 e8 ( ) d4 r8 d8 ( ) c4 r4 + $ +} + +begeleiding = voice { + $ \octave ``c + %%% theme + `c c e c f c e c d `b c `a `f `g `c2 + %%%% var 1 + r8 e8() c r8 e8() c r8 f8()c r8 e8()c + r8 d8()`b r8 c8()`a r8 `a8()`f r8 `e8()`c + $ +} + + +score { + melodicstaff { + voice { melodie } + } + melodicstaff { + voice { begeleiding } + } + paper { + unitspace 2.5cm + } + commands { + meter 2 4 + skip 16:0 + } +} \ No newline at end of file diff --git a/lexer.hh b/lexer.hh deleted file mode 100644 index ec7c9b929f..0000000000 --- a/lexer.hh +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef LEXER_HH -#define LEXER_HH - -#include "proto.hh" - -void new_input(String s); -bool close_input(); -int yylex(); -void yyerror(char *s); - -int lookup_keyword(String s); - -Identifier* lookup_identifier(String s); -void add_identifier(Identifier*i); -void delete_identifiers(); -#endif diff --git a/lexer.l b/lexer.l deleted file mode 100644 index 220b07ccf8..0000000000 --- a/lexer.l +++ /dev/null @@ -1,208 +0,0 @@ -%{ // -*-Fundamental-*- - -#include -#include -#include "glob.hh" -#include "string.hh" - -#include "lexer.hh" -#include "keyword.hh" -#include "vray.hh" -#include "parser.hh" -#include "debug.hh" - -sstack include_stack; -static int last_print; -const int DOTPRINT=50; // every 50 lines dots -%} - -%option c++ -%option noyywrap -%option nodefault -%option yylineno -%option debug -%x notes -%x incl -%x quote - -OPTSIGN !? -NOTENAMEI A|B|C|D|E|F|G|As|Bes|Ces|Des|Es|Fes|Ges|Ais|Bis|Cis|Dis|Eis|Fis|Gis -NOTENAMEII a|b|c|d|e|f|g|as|bes|ces|des|es|fes|ges|ais|bis|cis|dis|eis|fis|gis -NOTENAMEIII Ases|Beses|Ceses|Deses|Eses|Feses|Geses|Aisis|Bisis|Cisis|Disis|Eisis|Fisis|Gisis -NOTENAMEIIII ases|beses|ceses|deses|eses|feses|geses|aisis|bisis|cisis|disis|eisis|fisis|gisis -RESTNAME r|s -NOTENAME {NOTENAMEI}|{NOTENAMEII}|{NOTENAMEIII}|{NOTENAMEIIII} -PITCH ['`]*{OPTSIGN}{NOTENAME} -DURNAME 1|2|4|8|16|32 -DURATION {DURNAME}\.* -FULLNOTE {PITCH}{DURATION}? -WORD [a-zA-Z][a-zA-Z0-9_]+ -REAL [0-9]+(\.[0-9]*)? - -%% - -\$ { - BEGIN(notes); return '$'; -} - -{RESTNAME} { - const char *s = YYText(); - yylval.string = new String (s); - mtor << "rest:"<< yylval.string; - return RESTNAME; -} -{PITCH} { - const char *s = YYText(); - yylval.string = new String (s); - mtor << "pitch:"<< *yylval.string; - return PITCH; -} -{DURATION} { - yylval.string = new String (YYText()); - return DURATION; -} -[:space:]+ { -} -[ \t\n]+ { -} -%.* { - -} -\$ { - BEGIN(INITIAL); return '$'; -} -. { - error("lexer error: illegal character found: " + String(YYText())); -} - -\" { - BEGIN(quote); -} -[^\"]* { - yylval.string = new String (YYText()); -} -\" { - BEGIN(INITIAL); - return STRING; -} - -<> { - if(!close_input()) - yyterminate(); -} -{WORD} { - int l = lookup_keyword(YYText()); - if (l != -1) - return l; - Identifier * id = lookup_identifier(YYText()); - if (id) { - yylval.id = id; - return IDENTIFIER; - } - String *sp = new String( YYText()); - mtor << "new id: " << *sp; - yylval.string=sp; - return NEWIDENTIFIER; -} - -{REAL} { - Real r; - int cnv=sscanf (YYText(), "%lf", &r); - assert(cnv == 1); - mtor << "token (REAL)" << r; - yylval.real = r; - return REAL; -} - -[\{\}\[\]\(\)] { - - mtor << "parens\n"; - return YYText()[0]; -} -[:=] { - char c = YYText()[0]; - mtor << "misc char" <set_debug( !monitor.silence("Lexer")); - } - - lexer->switch_streams(newin); -} - - -// pop the inputstack. -bool -close_input() -{ - - istream *closing= include_stack.pop(); - if (closing != &cin) - delete closing; - - cout << "]" << flush; - - if (include_stack.empty()) - return false ; - else - lexer->switch_streams(include_stack.top()); - return true; -} - -int -yylex() { - return lexer->yylex(); -} - -void -yyerror(char *s) -{ - *mlog << "error in line " << lexer->lineno() << ": " << s << '\n'; - exit(1); -} - - -#if 0 - -{NOTENAME} { - yylval.string = new String (YYText()); - return NOTENAME; -} - -#endif diff --git a/lilyponddefs.tex b/lilyponddefs.tex index 41748636de..9cf064fee8 100644 --- a/lilyponddefs.tex +++ b/lilyponddefs.tex @@ -43,9 +43,13 @@ \mdef\doubledot{'01} \mdef\tripledot{'02} \mdef\mussepline{155} -\mdef\ieigthflag{45} -\mdef\isixteenthflag{46} -\mdef\ithirtysecondflag{47} + + +\mdef\deigthflag{45} +\mdef\dsixteenthflag{46} +\mdef\dthirtysecondflag{47} + +% pointing up \mdef\ueigthflag{40} \mdef\usixteenthflag{41} \mdef\uthirtysecondflag{42} @@ -55,10 +59,10 @@ \def\generalmeter#1#2{\vbox to 0pt{\vss\rm\hbox{#1}\hbox{#2}}} \def\lineseparator{\vbox{\mussepline\vskip -5pt\mussepline}} -\def\beauty{ - \par\vskip 10pt\par - \hskip -5pt\lineseparator% \hbox to 1cm{\kern -5mm\hrulefill} - \vskip 10pt +\def\beauty{% + \par\vskip 10pt plus 30pt minus 10pt\par + \hskip -5pt\lineseparator + \par\vskip 10pt plus 30pt minus 10pt\par } \def\interstaffline{% @@ -114,3 +118,5 @@ } +\def\beamslope#1#2{{\count0=#2\advance\count0 by#1\musicfnt\char\count0}} +\def\rulesym#1#2{\vrule height #1 width #2} \ No newline at end of file diff --git a/line.cc b/line.cc deleted file mode 100644 index 293214dc30..0000000000 --- a/line.cc +++ /dev/null @@ -1,137 +0,0 @@ -#include "line.hh" -#include "dimen.hh" -#include "spanner.hh" -#include "symbol.hh" -#include "paper.hh" -#include "pcol.hh" -#include "pscore.hh" - -static String -make_vbox(Interval i) -{ - - String s("\\vbox to "); - s += print_dimen(i.length()); - s += "{\\vskip "+print_dimen(i.max)+" "; - return s; -} - - -String -Line_of_staff::TeXstring() const -{ - String s("%line_of_staff\n"); - s+=make_vbox(height()); - // the staff itself: eg lines, accolades - s += "\\hbox{"; - { - Symbol sym = pstaff_->get_stafsym(scor->score->paper_->linewidth); - s+=sym.tex; - PCursor cc(scor->cols); - Real lastpos=cc->hpos; - - // all items in the current line & staff. - for (; cc.ok(); cc++) { - Real delta=cc->hpos - lastpos; - lastpos = cc->hpos; - - // moveover - if (delta) - s +=String( "\\kern ") + print_dimen(delta); - - // now output the items. - - for (PCursor ic(cc->its); ic.ok(); ic++) { - if (ic->pstaff_ == pstaff_) - s += ic->TeXstring(); - } - // spanners. - for (PCursor sc(cc->starters); sc.ok(); sc++) - if (sc->pstaff_ == pstaff_) - s += sc->TeXstring(); - } - } - s+="\\hss}\\vss}"; - return s; -} - -Line_of_staff::Line_of_staff(Line_of_score * sc, PStaff*st) -{ - - scor=sc; - pstaff_=st; - - const PCol *linestart= sc->cols.top(); - const PCol *linestop=sc->cols.bottom(); - - for (PCursor sp(pstaff_->spans); sp.ok(); sp++) { - const PCol *brokenstart = &MAX(*linestart, *sp->left); - const PCol *brokenstop = &MIN(*linestop, *sp->right); - - if (*brokenstop < *brokenstart) - brokenspans.bottom().add(sp->broken_at(brokenstop, brokenstart)); - } -} - - -Interval -Line_of_staff::height() const -{ - Interval y; - { - Symbol s = pstaff_->stafsym->eval(scor->score->paper_->linewidth); - y = s.dim.y; - } - PCursor cc(scor->cols); - - // all items in the current line & staff. - for (; cc.ok(); cc++) { - for (PCursor ic(cc->its); ic.ok(); ic++) { - if (ic->pstaff_ == pstaff_) { - y.unite(ic->height()); - } - - // spanners. - for (PCursor sc(cc->starters); sc.ok(); sc++) - if (sc->pstaff_ == pstaff_) - assert(false); - } - } - return y; -} - - -/****************************************************************/ -String -Line_of_score::TeXstring() const -{ - String s("\\vbox{%<- line of score\n"); - for (PCursor sc(staffs); sc.ok(); sc++){ - s += sc->TeXstring(); - if ((sc+1).ok()) - s+= "\\interstaffline\n"; - } - s += "}"; - return s; -} - -/// testing this entry -Line_of_score::Line_of_score(svec sv, - const PScore *ps) -{ - score = ps; - for (int i=0; i< sv.sz(); i++) { - PCol *p=(PCol *) sv[i]; - cols.bottom().add(p); - p->line=this; - } - - for (PCursor sc(score->staffs); sc.ok(); sc++) - staffs.bottom().add(new Line_of_staff(this, sc)); -} -/** construct a line with the named columns. Make the line field - in each column point to this - - #sv# isn't really const!! - */ - diff --git a/line.hh b/line.hh deleted file mode 100644 index 641ddf257d..0000000000 --- a/line.hh +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef LINE_HH -#define LINE_HH - -/* - horizontal structures for broken scores. -*/ - -#include "real.hh" -#include "plist.hh" -#include "vray.hh" -#include "glob.hh" -#include "pstaff.hh" - - - -/// the columns of a score that form one line. -struct -Line_of_score { - List cols; - - // need to store height of each staff. - PointerList staffs; - const PScore * score; // needed to generate staffs - - /****************/ - - Line_of_score(svec sv, const PScore *); - - String TeXstring() const; - - // is #c# contained in #*this#? - bool element(const PCol *c); -}; - -/// one broken line of staff. -struct Line_of_staff { - PointerList brokenspans; - Line_of_score const * scor; - const PStaff *pstaff_; - - /****************/ - - String TeXstring() const; - Line_of_staff(Line_of_score*, PStaff *); - Interval height() const; -}; - -#endif diff --git a/linespace.cc b/linespace.cc deleted file mode 100644 index 17c16ef4ef..0000000000 --- a/linespace.cc +++ /dev/null @@ -1,259 +0,0 @@ -#include -#include "linespace.hh" -#include "debug.hh" -#include "qlp.hh" -#include "unionfind.hh" - -const Real COLFUDGE=1e-3; -//#define COLFUDGE 1e-3 -bool -Spacing_problem::contains(const PCol *w) -{ - for (int i=0; i< cols.sz(); i++) - if (cols[i].col == w) - return true; - return false; -} - -int -Spacing_problem::col_id(const PCol *w)const -{ - for (int i=0; i< cols.sz(); i++) - if (cols[i].col == w) - return i; - assert(false); -} - -void -Spacing_problem::OK() const -{ -#ifndef NDEBUG - Union_find connected(cols.sz()); - - for (int i=0; i < ideals.sz(); i++) { - assert(ideals[i]->hooke > 0); - int l = col_id(ideals[i]->left); - int r = col_id(ideals[i]->right); - connected.connect(l,r); - } - - for (int i = 0; i < cols.sz(); i++) { - assert( connected.equiv(0,i)); - } -#endif -} - -bool -Spacing_problem::check_constraints(Vector v) const -{ - int dim=v.dim(); - // mtor << "checking solution " << v << '\n'; - for (int i=0; i < dim; i++) { - - if (cols[i].fixed&& ABS(cols[i].fixpos - v(i)) > COLFUDGE) { - return false; - } - if (!i) - continue; - - Real mindist=cols[i-1].minright() - +cols[i].minleft(); - - // ugh... compares - Real dif =v(i) - v(i-1)- mindist; - bool b = (dif > - COLFUDGE); - - -#if 1 - if (!b) - return false; - -#else - mtor << "dif= "<fudge= "<< - b << "\n"; - - /* fucks up for unknown reasons */ - if (dif < -COLFUDGE) - return false; -#endif - - } - return true; -} - -bool -Spacing_problem::check_feasible() const -{ - Vector sol(try_initial_solution()); - return check_constraints(sol); -} - -// generate a solution which obeys the min distances and fixed positions -Vector -Spacing_problem::try_initial_solution() const -{ - int dim=cols.sz(); - Vector initsol(dim); - for (int i=0; i < dim; i++) { - if (cols[i].fixed) { - initsol(i)=cols[i].fixpos; - } else { - Real mindist=cols[i-1].minright() - +cols[i].minleft(); - assert(mindist >= 0.0); - initsol(i)=initsol(i-1)+mindist; - - //nog niet - //if (i>0) - // assert(initsol(i) > initsol(i-1)); - } - } - - return initsol; -} -Vector -Spacing_problem::find_initial_solution() const -{ - Vector v(try_initial_solution()); - assert(check_constraints(v)); - return v; -} -// generate the matrices -void -Spacing_problem::make_matrices(Matrix &quad, Vector &lin, Real &c) const -{ - quad.fill(0); - lin.fill(0); - for (int j=0; j < ideals.sz(); j++){ - Idealspacing const*i=ideals[j]; - int l = col_id(i->left); - int r = col_id(i->right); - - quad(r,r) += i->hooke; - quad(r,l) -= i->hooke; - quad(l,r) -= i->hooke; - quad(l,l) += i->hooke; - - lin(r) -= i->space*i->hooke; - lin(l) += i->space*i->hooke; - - c += sqr(i->space); - } -} - -// put the constraints into the LP problem -void -Spacing_problem::make_constraints(Mixed_qp& lp) const -{ - int dim=cols.sz(); - for (int j=0; j < dim; j++) { - Colinfo *c=&(cols[j]); - if (c->fixed) { - lp.add_fixed_var(j,c->fixpos); - } - if (j > 0){ - Vector c1(dim); - - - c1(j)=1.0 ; - c1(j-1)=-1.0 ; - lp.add_inequality_cons(c1, cols[j-1].minright() + - cols[j].minleft()); - } - } -} - -svec -Spacing_problem::solve() const -{ - print(); - OK(); - assert(check_feasible()); - - - /* optimalisatiefunctie */ - Mixed_qp lp(cols.sz()); - make_matrices(lp.quad,lp.lin, lp.const_term); - make_constraints(lp); - Vector start=find_initial_solution(); - Vector sol(lp.solve(start)); - if (!check_constraints(sol)) { - WARN << "solution doesn't satisfy constraints.\n" ; - } - - - svec posns(sol); - posns.add(lp.eval(sol)); - return posns; -} - -/* - add one column to the problem. -*/ -void -Spacing_problem::add_column(const PCol *col, bool fixed, Real fixpos) -{ - Colinfo c; - c.fixed=fixed; - c.fixpos=fixpos; - assert(col); - c.col=col; - cols.add(c); -} - -void -Spacing_problem::add_ideal(const Idealspacing *i) -{ - const PCol *l =i->left; - const PCol *r= i->right; - - if (!contains(l) || !contains(r)) { - return; - } - ideals.add(i); -} - -void -Spacing_problem::print_ideal(const Idealspacing*id)const -{ -#ifndef NPRINT - int l = col_id(id->left); - int r = col_id(id->right); - - mtor << "between " << l <<","<width().max; } - Real minleft()const { return -col->width().min; } -}; - - -/// spacing for one line. -class Spacing_problem { - svec ideals; - svec cols; - - /// the index of #c# in #cols# - int col_id(const PCol *c) const; - - /// generate an (nonoptimal) solution - Vector find_initial_solution() const; - - /// check if problem is too tight - bool check_feasible() const; - /// does #this# contain the column #w#? - bool contains(const PCol *w); - - /// make the energy function - void make_matrices(Matrix &quad, Vector &lin,Real&) const; - - /// generate the LP constraints - void make_constraints(Mixed_qp& lp) const; - -public: - /// solve the spacing problem - svec solve() const; - /** - return the column positions, and the energy (last element) - */ - /// add a idealspacing to the problem. - void add_ideal(const Idealspacing *i); - - /** - One pair of columns can have no, one or more idealspacings, - since they can be "summed" if the columns to which #i# refers are - not in this problem, the spacing is ignored. - */ - - - /// add a col to the problem - void add_column(const PCol *, bool fixed=false, Real fixpos=0.0); - /** columns have to be added left to right. The column contains - info on it's minimum width. - */ - - - bool check_constraints(Vector v) const; - - Vector try_initial_solution() const; - void OK() const; - void print() const; - void print_ideal(const Idealspacing*)const; -}; - - -/** the problem, given by the columns (which include constraints) and - intercolumn spacing. The problem is: - - Generate a spacing which - \begin{itemize} - \item - Satisfies spacing constraints (notes can't be printed through each other) - \item - Looks good, ie tries to conform to an ideal spacing as much as possible. - \end{itemize} - This is converted by regarding idealspacing as "springs" attached - to columns. The equilibrium of one spring is the ideal - distance. The columns have a size, this imposes "hard" constraints - on the distances. This transforms the problem into a quadratic - programming problem with linear constraints. - - The quality is given by the total potential energy in the - springs. The lower the energy, the better the configuration. -*/ -#endif diff --git a/linestaff.cc b/linestaff.cc deleted file mode 100644 index 7cd081dc49..0000000000 --- a/linestaff.cc +++ /dev/null @@ -1,20 +0,0 @@ -#include "linestaff.hh" -#include "symbol.hh" -#include "lookupsyms.hh" -#include "dimen.hh" -#include "paper.hh" -#include "pscore.hh" - -Linestaff::Linestaff(int l, PScore *s) - : PStaff(s) -{ - nolines = l; - stafsym = s->paper_->lookup_->linestaff(l); -} - -Symbol -Linestaff::get_stafsym(Real width)const -{ - String w(print_dimen(width)); - return stafsym->eval(w); -} diff --git a/linestaff.hh b/linestaff.hh deleted file mode 100644 index 891269dd9d..0000000000 --- a/linestaff.hh +++ /dev/null @@ -1,11 +0,0 @@ -#include "pstaff.hh" - -struct Linestaff : PStaff { - - int nolines; - -/****************/ - - Symbol get_stafsym(Real width)const; - Linestaff(int, PScore*); -}; diff --git a/lookupsyms.cc b/lookupsyms.cc deleted file mode 100644 index e6ad52ca5a..0000000000 --- a/lookupsyms.cc +++ /dev/null @@ -1,160 +0,0 @@ -#include "lookupsyms.hh" -#include "debug.hh" -#include "symtable.hh" -#include "dimen.hh" -#include "tex.hh" - -void -Lookup::parse(Text_db&t) -{ - symtables_->read(t) ; -} - -Lookup::Lookup() -{ - symtables_ = new Symtables; -} - -Lookup::~Lookup() -{ - delete symtables_; -} - -Symbol -Lookup::ball(int j) -{ - if (j > 4) - j = 4; - - Symtable * st = (*symtables_)("balls"); - return st->lookup(String(j)); -} - -Symbol -Lookup::rest(int j) -{ - return (*symtables_)("rests")->lookup(String(j)); -} - - -Symbol -Lookup::bar(String s) -{ - return (*symtables_)("bars")->lookup(s); -} - Symbol -Lookup::dots(int j) -{ - if (j>3) - error("max 3 dots"); - return (*symtables_)("dots")->lookup(j); -} - -Symbol -Lookup::flag(int j) -{ - 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 a; - a.add(arg); - ret.tex = substitute_args(ret.tex, a); - - return ret; -} - -/****************************************************************/ -// bare bones. - -struct Linestaf_symbol : Parametric_symbol { - int lines; - Linestaf_symbol(int n, Symtables*s): Parametric_symbol(s) { lines = n;} - Symbol eval(svec)const; -}; - - -Symbol -Linestaf_symbol::eval(svec w)const -{ - Real wid = w[0].fvalue(); - - Symbol s; - s.dim.x = Interval(0,wid); - Real dy=(lines-1)*convert_dimen(5,"pt"); // TODO! - s.dim.y = Interval(0,dy); - svec a; - a.add(lines); - a.add(w[0]); - s.tex = (*symtables_)("param")->lookup("linestaf").tex; - s.tex = substitute_args(s.tex, a); - return s; -} - -/****************************************************************/ - - -struct Meter_sym:Parametric_symbol { - - Meter_sym(Symtables*s) : Parametric_symbol(s){ } - Symbol eval(svec a) const{ - Symbol s; - s.dim.x = Interval( convert_dimen(-5,"pt"), - convert_dimen(5,"pt")); - s.dim.y = Interval(0, convert_dimen(10,"pt") ); // todo - String src = (*symtables_)("param")->lookup("meter").tex; - s.tex = substitute_args(src,a); - return s; - } -}; -/****************************************************************/ - -struct Stem_sym:Parametric_symbol { - - Stem_sym(Symtables*s) : Parametric_symbol(s) { } - Symbol eval(svec a) const { - Real y1 = a[0].fvalue(); - Real y2 = a[1].fvalue(); - assert(y1 <= y2); - Symbol s; - s.dim.x = Interval(0,0); - s.dim.y = Interval(y1,y2); - - String src = (*symtables_)("param")->lookup("stem").tex; - s.tex = substitute_args(src,a); - return s; - } -}; - -Parametric_symbol * -Lookup::meter(String ) -{ - return new Meter_sym(symtables_); -} - -Parametric_symbol * -Lookup::linestaff(int n) -{ - return new Linestaf_symbol(n,symtables_); -} - -Parametric_symbol* -Lookup::stem() -{ - return new Stem_sym(symtables_); -} diff --git a/lookupsyms.hh b/lookupsyms.hh deleted file mode 100644 index 1ec0d04d10..0000000000 --- a/lookupsyms.hh +++ /dev/null @@ -1,34 +0,0 @@ -/* - lilypond, (c) 1996 Han-Wen Nienhuys -*/ -#ifndef LOOKUPSYMS_HH -#define LOOKUPSYMS_HH - -#include "symbol.hh" - -struct Lookup { - Symtables *symtables_; - - /****************/ - - void parse (Text_db&t); - 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); - Symbol bar(String); - Symbol dots(int); - Lookup(); - ~Lookup(); -}; - -#endif diff --git a/maartje.ly b/maartje.ly index e12fc345e6..4c32f09c9a 100644 --- a/maartje.ly +++ b/maartje.ly @@ -2,20 +2,29 @@ ritme = rhythmstaff { voice { $ c2 r32 r32 r16 r8 r4 c2 c2 c2 c2 c2 c2 c2 c2 c2 c2 c2 c2 c2 c2 c2 c2 c2 c2 c2 $ } } + 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] [d8 e8 f8 g8] + ''fis1 + a8 b8 'c8 'd8 ''c8 ```c8 c4 c4 c4 c4 + \duration 16 `b16 `a16 `g16 `f16 \duration 4 + c `b `a `g `f `e `d `c ``b ``a ``g ``f ``e ``d ``c$ + } } score { paper { - unitspace 3 cm + geometric 1.4 + unitspace 3.0 cm } staff { ritme } staff { melody } % staff { melody } commands { meter 4 4 - skip 3:0 + skip 2:0 meter 2 4 skip 19:0 } diff --git a/main.cc b/main.cc deleted file mode 100644 index 3c33fd959d..0000000000 --- a/main.cc +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include -#include "lgetopt.hh" -#include "misc.hh" -#include "string.hh" -#include "main.hh" - -extern void parse_file(String s); - -long_option_init theopts[] = { - 1, "output", 'o', - 0, "warranty", 'w', - 0,0,0 -}; - - -void notice() -{ - cout << - "LilyPond, a music typesetter.\n" - "Copyright (C) 1996 by\n" - " Han-Wen Nienhuys \n" - "\n" - "\n" - " This program is free software; you can redistribute it and/or\n" - "modify it under the terms of the GNU General Public License version 2\n" - "as published by the Free Software Foundation.\n" - "\n" - " This program is distributed in the hope that it will be useful,\n" - "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" - "General Public License for more details.\n" - "\n" - " You should have received a copy (refer to the file COPYING) of the\n" - "GNU General Public License along with this program; if not, write to\n" - "the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,\n" - "USA.\n"; -} - -int -main (int argc, char **argv) -{ - Getopt_long oparser(argc, argv,theopts); - debug_init(); - cout << get_version(); - - while (long_option_init * opt = oparser()) { - switch ( opt->shortname){ - case 'o': - set_default_output(oparser.optarg); - break; - case 'w': - notice(); - exit(0); - break; - default: - assert(false); - break; - } - } - char *arg = oparser.get_next_arg(); - - if (!arg) arg = ""; - parse_file(arg); - - do_scores(); - exit (0); -} diff --git a/main.hh b/main.hh deleted file mode 100644 index 58928f5142..0000000000 --- a/main.hh +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef MAIN_HH -#define MAIN_HH -#include "proto.hh" - -void debug_init(); -void do_scores(); -void add_score(Score * s); -void set_default_output(String s); -const char *get_version(); - -#endif diff --git a/make_patch b/make_patch index 2e9246f4d7..8747fe6b84 100755 --- a/make_patch +++ b/make_patch @@ -3,29 +3,30 @@ old=$1 new=$2 nm=$3- -newarc=$nm$new.tar.gz -oldarc=$nm$old.tar.gz +newarc=../releases/$nm$new.tar.gz +oldarc=../releases/$nm$old.tar.gz if [ ! -x $nm$new ] then echo untarring .. - tar zfxv $nm$new.tar.gz if [ ! -f $newarc ] then echo cant find $newarc exit fi + tar zfxv $newarc fi if [ ! -x $nm$old ] then echo untarring - tar zfxv $nm$old.tar.gz + if [ ! -f $oldarc ] then echo cant find oldarc exit fi + tar zfxv $oldarc fi #(cd $nm$old; touch depend; make clean) diff --git a/melodicstaff.cc b/melodicstaff.cc deleted file mode 100644 index 2937f45dfe..0000000000 --- a/melodicstaff.cc +++ /dev/null @@ -1,78 +0,0 @@ -#include "melodicstaff.hh" -#include "stem.hh" -#include "notehead.hh" -#include "paper.hh" -#include "molecule.hh" -#include "linestaff.hh" -#include "rhythmstaff.hh" -#include "sccol.hh" - -const int NO_LINES=5; -const int BOTTOM_POSITION=2; // e is on bottom line of 5-staff... - -void -Melodic_staff::set_output(PScore*ps) -{ - theline = new Linestaff(NO_LINES,ps); - Simple_staff::set_output(ps); -} - -void -Melodic_column::typeset_command(Command *com, int breakst) -{ - Molecule*m=create_command_mol(com); - Item *i =new Item; - i->output = m; - typeset_item(i, breakst); -} - -void -Melodic_column::typeset_req(Request *rq) -{ - Item *i ; - if (rq->note()) { - 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; - } - typeset_item(i); -} - - -void -Melodic_column::typeset_stem(Stem_req*rq) -{ - Stem * s = new Stem(NO_LINES); - int n = the_note->note()->height()-BOTTOM_POSITION; - s->minnote =s->maxnote=n; - s->flag = rq->stem_number; - typeset_item(s); -} - -/* - creation - */ -Staff * -get_new_melodicstaff() -{ - return new Melodic_staff; -} - - -Staff_column* -Melodic_staff::create_col(Score_column*s) -{ - return new Melodic_column(s,this); -} - -Melodic_staff* -Melodic_staff::clone()const -{ - return new Melodic_staff(*this); -} diff --git a/melodicstaff.hh b/melodicstaff.hh deleted file mode 100644 index 5c417b84a5..0000000000 --- a/melodicstaff.hh +++ /dev/null @@ -1,32 +0,0 @@ -/* - rhythmstaf.hh -- part of LilyPond - - (c) 1996 Han-Wen Nienhuys -*/ - -#ifndef MELODICSTAFF_HH -#define MELODICSTAFF_HH - -#include "simplestaff.hh" - -/// five line staff, no multiple voices -struct Melodic_staff : public Simple_staff -{ - Staff_column * create_col(Score_column*); - virtual void set_output(PScore *); - virtual Melodic_staff*clone()const; -}; - -struct Melodic_column : public Simple_column { - virtual void typeset_req(Request *rq); - virtual void typeset_stem(Stem_req *rq); - virtual void typeset_command(Command *, int brs); - // virtual void typeset_item(Item*, int=1); - Melodic_column(Score_column*s,Simple_staff*rs) : - Simple_column(s,rs) { } -// virtual Melodic_column*clone()const; -}; - -#endif // MELODICSTAFF_HH - - diff --git a/misc.cc b/misc.cc deleted file mode 100644 index 54746fd836..0000000000 --- a/misc.cc +++ /dev/null @@ -1,14 +0,0 @@ -#include "misc.hh" -#include "glob.hh" - -#include - -int intlog2(int d) { - int i=0; - while (!(d&1)) { - d/= 2; i++; - } - assert(!(d/2)); - return i; -} - diff --git a/misc.hh b/misc.hh deleted file mode 100644 index 64c8ca4102..0000000000 --- a/misc.hh +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef MISC_HH -#define MISC_HH - - - - -#endif diff --git a/molecule.cc b/molecule.cc deleted file mode 100644 index 8fca34836b..0000000000 --- a/molecule.cc +++ /dev/null @@ -1,127 +0,0 @@ -#include "glob.hh" -#include "dimen.hh" -#include "string.hh" -#include "molecule.hh" -#include "symbol.hh" -#include "debug.hh" - -void -Atom::print() const -{ - mtor << "texstring: " < a; - a.add(print_dimen(off.y)); - a.add(print_dimen(off.x)); - a.add(sym.tex); - return substitute_args(s, a); -} - - -String -Molecule::TeXstring() const -{ - String s; - for(PCursor c(ats); c.ok(); c++) - s+=c->TeXstring(); - return s; -} - -Box -Molecule::extent() const -{ - Box b; - for(PCursor c(ats); c.ok(); c++) - b.unite(c->extent()); - return b; -} - -void -Molecule::translate(Offset o) -{ - for (PCursor c(ats); c.ok(); c++) - c->translate(o); -} - -void -Molecule::add(const Molecule &m) -{ - for (PCursor c(m.ats); c.ok(); c++) { - add(**c); - } -} - -void -Molecule::add_right(const Molecule &m) -{ - Real xof=extent().x.max - m.extent().x.min; - Molecule toadd(m); - toadd.translate(Offset(xof, 0.0)); - add(toadd); -} - -void -Molecule::add_left(const Molecule &m) -{ - Real xof=extent().x.min - m.extent().x.max; - Molecule toadd(m); - toadd.translate(Offset(xof, 0.0)); - add(toadd); -} - - -void -Molecule::add_top(const Molecule &m) -{ - Real yof=extent().y.max - m.extent().y.min; - Molecule toadd(m); - toadd.translate(Offset(0,yof)); - add(toadd); -} - -void -Molecule::add_bot(const Molecule &m) -{ - Real yof=extent().y.min- m.extent().y.max; - Molecule toadd(m); - toadd.translate(Offset(0,yof)); - add(toadd); -} - -void -Molecule::operator = (const Molecule&) -{ - assert(false); -} - -Molecule::Molecule(const Molecule&s) -{ - add(s); -} - -void -Molecule::print() const -{ - for (PCursor c(ats); c.ok(); c++) - c->print(); -} diff --git a/molecule.hh b/molecule.hh deleted file mode 100644 index 0c69f74040..0000000000 --- a/molecule.hh +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef MOLECULE_HH -#define MOLECULE_HH - -#include "plist.hh" -#include "boxes.hh" -#include "item.hh" -#include "symbol.hh" -/// a symbol which can be translated, and freely copied -struct Atom { - Offset off; - Symbol sym; - - void translate(Offset o) { - off += o; - } - - /// how big is #this#? - Box extent() const; - Atom(Symbol s); - - void print() const; - - String TeXstring() const; -}; - -/// a group of #Atom#s -struct Molecule { - PointerList ats; - - Molecule() { } - Molecule(Atom a) { add(a) ; } - - void add_right(const Molecule &m); - void add_left(const Molecule &m); - void add_top(const Molecule &m); - void add_bot(const Molecule &m); - void add(Molecule const &m); - void translate(Offset); - void add(Atom a) { ats.bottom().add(new Atom(a)); } - /// how big is #this#? - Box extent() const; - - String TeXstring() const; - - Molecule(const Molecule&s); - void print() const; -private: - void operator=(const Molecule&); -}; -/** a group of individually translated symbols. You can add molecules - to the top, to the right, etc. */ -#endif diff --git a/note.cc b/note.cc deleted file mode 100644 index b897ce0e66..0000000000 --- a/note.cc +++ /dev/null @@ -1,141 +0,0 @@ -#include -#include "string.hh" -#include "real.hh" -#include "debug.hh" -#include "request.hh" -#include "voice.hh" -#include "notename.hh" - -int default_duration = 4; - -void -parse_duration(const char *a, int &j, int &intdur, int &dots) -{ - String durstr; - while (isdigit(a[j])) - { - durstr += a[j++]; - } - - dots=0; - - while (a[j] == '.') - { - j++; - dots++; - } - intdur = (durstr.len()) ? - durstr.value():default_duration; - - - mtor << "dur " << intdur << "dots " << dots<= 2) { - Stem_req * st = new Stem_req(v, dur); - v->add(st); - } - - int oct, pit, acc; - bool forceacc; - parse_pitch(pitch, i, oct, forceacc, pit, acc); - char nm = pit + 'c'; - if (nm > 'g') - nm += 'a' - 'h'; - rq->name =nm; - - rq->octave = oct; - rq->accidental = acc; - rq->forceacc = forceacc; - rq->balltype = dur; - rq->dots = dots; - - rq->print(); - - v->add(rq); - - return v; -} - -Voice_element * -get_rest_element(String, String durstr) -{ - Voice_element*v = new Voice_element; - int i=0; - - int dur, dots; - parse_duration(durstr, i, dur, dots); - i=0; - - Rest_req * rq = new Rest_req(v); - - rq->balltype = dur; - rq->dots = dots; - rq->print(); - v->add(rq); - return v; -} diff --git a/notehead.cc b/notehead.cc deleted file mode 100644 index fe026b1036..0000000000 --- a/notehead.cc +++ /dev/null @@ -1,67 +0,0 @@ -#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 "<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)); -} - diff --git a/notehead.hh b/notehead.hh deleted file mode 100644 index b694e95af8..0000000000 --- a/notehead.hh +++ /dev/null @@ -1,38 +0,0 @@ -/* - 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 - diff --git a/notename.cc b/notename.cc deleted file mode 100644 index 8ebc4df244..0000000000 --- a/notename.cc +++ /dev/null @@ -1,30 +0,0 @@ -#include "glob.hh" -#include "string.hh" - - -/// change this along with lex file for other notenames. -const char *notetab[] = -{ -"ceses", "ces", "c", "cis", "cisis", -"deses", "des", "d", "dis", "disis", -"eses", "es", "e", "eis", "eisis", -"feses", "fes", "f", "fis", "fisis", -"geses", "ges", "g", "gis", "gisis", -"ases", "as", "a", "ais", "aisis", -"beses", "bes", "b", "bis", "bisis", -0 -}; - -void -lookup_notename(int &large, int &small, String s) -{ - int i; - for (i =0; notetab[i]; i++) - if (s == notetab[i]) - { - large = i /5; - small = i %5 - 2; - return; - } - assert(false); -} diff --git a/notename.hh b/notename.hh deleted file mode 100644 index ef04a0da7c..0000000000 --- a/notename.hh +++ /dev/null @@ -1,2 +0,0 @@ - -void lookup_notename(int &large, int &small, String s); diff --git a/objects/Makefile b/objects/Makefile new file mode 100644 index 0000000000..701ad6d5b9 --- /dev/null +++ b/objects/Makefile @@ -0,0 +1,2 @@ +dist: + ln Makefile $(DDIR)/objects/ \ No newline at end of file diff --git a/paper.cc b/paper.cc deleted file mode 100644 index 89f9a9fe5c..0000000000 --- a/paper.cc +++ /dev/null @@ -1,78 +0,0 @@ -#include - -#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() -{ - lookup_ = new Lookup(); - parse(); - linewidth = convert_dimen(15,"cm"); // in cm for now - whole_width= 6*note_width(); - geometric_ = PHI; -} - -void -Paperdef::parse() -{ - Text_db symini("symbol.ini"); - - - while (!symini.eof()) { - - Text_record r( symini++); - - if (r[0] == "symboltables") - lookup_->parse(symini); - } -} - -Paperdef::~Paperdef() -{ - delete lookup_; -} - -Real -Paperdef::interline() const -{ - return lookup_->ball(4).dim.y.length(); -} -Real -Paperdef::note_width()const -{ - return lookup_->ball(4).dim.x.length( ); -} -Real -Paperdef::standard_height() const -{ - return convert_dimen(20,"pt"); -} - -void -Paperdef::print() const -{ -#ifndef NPRINT - mtor << "Paper {width: " << print_dimen(linewidth); - mtor << "whole: " << print_dimen(whole_width); - mtor << "out: " < - -#include "lexer.hh" -#include "paper.hh" -#include "staff.hh" -#include "score.hh" -#include "main.hh" -#include "keyword.hh" -#include "scommands.hh" -#include "debug.hh" -#include "parseconstruct.hh" -#include "dimen.hh" -#include "identifier.hh" - -#ifndef NDEBUG -#define YYDEBUG 1 -#endif - -%} - - -%union { - Real real; - Command *command; - Identifier *id; - Score_commands *scommands; - Voice *voice; - Voice_element *el; - Staff *staff; - String *string; - Score *score; - const char *consstr; - Paperdef *paper; - int i; -} - -%token VOICE STAFF SCORE TITLE RHYTHMSTAFF BAR NOTENAME OUTPUT -%token CM IN PT MM PAPER WIDTH METER UNITSPACE SKIP COMMANDS -%token MELODICSTAFF GEOMETRIC START - -%type unit -%token IDENTIFIER -%token NEWIDENTIFIER -%token PITCH DURATION RESTNAME -%token REAL -%token STRING -%type declaration -%type paper_block paper_body -%type dim -%type voice_block voice_body voice_elts voice_elts_dollar -%type voice_elt -%type score_command -%type score_block score_body -%type staff_block rhythmstaff_block rhythmstaff_body -%type melodicstaff_block melodicstaff_body staffdecl -%type int -%type score_commands_block score_commands_body - -%% - -mudela: /* empty */ - | mudela score_block { - add_score($2); - } - | mudela add_declaration { } - ; - -add_declaration: declaration { - add_identifier($1); - } - ; - -declaration: - NEWIDENTIFIER '=' staff_block { - $$ = new Staff_id(*$1, $3); - delete $1; // this sux - } - | NEWIDENTIFIER '=' voice_block { - $$ = new Voice_id(*$1, $3); - delete $1; - } - ; - - -score_block: SCORE '{' score_body '}' { $$ = $3; } - ; - -score_body: { $$ = new Score; } - | score_body staff_block { $$->add($2); } - | score_body score_commands_block { $$->set($2); } - | score_body paper_block { $$->set($2); } - ; -score_commands_block: - COMMANDS '{' score_commands_body '}' { $$ =$3;} - ; - -score_commands_body: { $$ = new Score_commands; } - | score_commands_body score_command { - $$->parser_add($2); - } - ; - -paper_block: - PAPER '{' paper_body '}' { $$ = $3; } - ; - -paper_body: - /* empty */ { $$ = new Paperdef; } - | paper_body WIDTH dim { $$->linewidth = $3;} - | paper_body OUTPUT STRING { $$->outfile = *$3; - delete $3; - } - | paper_body UNITSPACE dim { $$->whole_width = $3; } - | paper_body GEOMETRIC REAL { $$->geometric_ = $3; } - ; - -dim: - REAL unit { $$ = convert_dimen($1,$2); } - ; - - -unit: CM { $$ = "cm"; } - |IN { $$ = "in"; } - |MM { $$ = "mm"; } - |PT { $$ = "pt"; } - ; - -/* - staff -*/ -staff_block: - staffdecl - | rhythmstaff_block - | melodicstaff_block - ; - -staffdecl: STAFF '{' IDENTIFIER '}' { $$ = $3->staff()->clone(); } - ; - -rhythmstaff_block: - RHYTHMSTAFF '{' rhythmstaff_body '}' { $$ = $3; } - ; - -rhythmstaff_body: - /* empty */ { $$ = get_new_rhythmstaff(); } - | rhythmstaff_body voice_block { $$->add_voice($2); } - ; - -melodicstaff_block: - MELODICSTAFF '{' melodicstaff_body '}' { $$ = $3; } - ; - -melodicstaff_body: - /* empty */ { $$ = get_new_melodicstaff(); } - | melodicstaff_body voice_block { $$->add_voice($2); } - ; - -/* - voice -*/ -voice_block: - VOICE '{' voice_body '}' { $$ = $3; } - ; - - -voice_body: - IDENTIFIER { $$ = new Voice(*$1->voice()); } - | voice_elts_dollar { $$ = $1; } - | voice_body START REAL { $$->start = $3; } - ; - - - - -voice_elts_dollar: - '$' voice_elts '$' { $$ = $2; } - ; - -voice_elts: - /* empty */ { - $$ = new Voice; - } - | voice_elts voice_elt { - $$->add($2); - } - ; - -voice_elt: - PITCH DURATION { $$ = get_note_element(*$1, *$2); - - } - | RESTNAME DURATION { $$ = get_rest_element(*$1, *$2); - - } - ; - -score_command: - SKIP int ':' REAL { - $$ = get_skip_command($2, $4); - } - | METER int int { - $$ = get_meterchange_command($2, $3); - } -/* | PARTIALMEASURE REAL { - $$ = get_partial_command($2); - }*/ - ; - - -int: - REAL { - $$ = int($1); - if (ABS($1-Real(int($$))) > 1e-8) - yyerror("expecting integer number"); - - } - ; - -%% - -void -parse_file(String s) -{ - *mlog << "Parsing ... "; -#ifdef YYDEBUG - yydebug = !monitor.silence("Parser"); -#endif - new_input(s); - yyparse(); - delete_identifiers(); - *mlog << "\n"; -} diff --git a/pcol.cc b/pcol.cc deleted file mode 100644 index 1ae06519ac..0000000000 --- a/pcol.cc +++ /dev/null @@ -1,117 +0,0 @@ -#include "pcol.hh" -#include "pstaff.hh" -#include "debug.hh" - -void -Idealspacing::print() const -{ -#ifndef NPRINT - mtor << "idealspacing {" ; - mtor << "distance "<= 0 && left && right); -#endif -} - -/****************************************************************/ - -Interval -PCol::width() const -{ - Interval w; - - for (PCursor ic(its); ic.ok(); ic++) - w.unite(ic->width()); - if (w.empty()) - w.unite(Interval(0,0)); - return w; -} - -void -PCol::print() const -{ - #ifndef NPRINT - mtor << "PCol {"; - mtor << "# symbols: " << its.size() ; - if (breakable()){ - mtor << "pre,post: "; - prebreak->print(); - postbreak->print(); - } - mtor << "extent: " << width().min << ", " << width().max << "\n"; - mtor << "}\n"; - #endif -} - -int -PCol::compare(const PCol &, const PCol &) -{ - assert(false); - return 0 ; -} - -void -PCol::OK () const -{ - if (prebreak || postbreak ) { - assert(prebreak&&postbreak); - assert(prebreak->daddy == this); - assert(postbreak->daddy == this); - } - -} - -void -PCol::set_breakable() -{ - if (breakable()) - return; - - prebreak = new PCol(this); - postbreak = new PCol(this); - used = true; -} - -bool -PCol::breakable() const -{ - return prebreak||postbreak; -} - -PCol::PCol(PCol *parent) { - daddy = parent; - prebreak=0; - postbreak=0; - line=0; - used = false; -} - -PCol::~PCol() -{ - - delete prebreak; - - delete postbreak; -} - -void -PCol::add(const Item *i) -{ - its.bottom().add(i); - used = true; -} - diff --git a/pcol.hh b/pcol.hh deleted file mode 100644 index f28617190a..0000000000 --- a/pcol.hh +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef COLS_HH -#define COLS_HH - -#include "glob.hh" -#include "boxes.hh" -#include "plist.hh" -#include "item.hh" - -/// stuff grouped vertically. -struct PCol { - List its; - List stoppers, starters; - - /// Can this be broken? true eg. for bars. - bool breakable()const; - - /// does this column have items, does it have spacings attached? - bool used; - - /// prebreak is put before end of line. - PCol *prebreak; - /** - if broken here, then (*this) column is discarded, and prebreak - is put at end of line, owned by Col - */ - - /// postbreak at beginning of the new line - PCol *postbreak; - /** \See{prebreak} - */ - PCol *daddy; - /* - if this column is pre or postbreak, then this field points to the parent. - */ - /// if lines are broken then this column is in #line# - const Line_of_score *line; - - /// if lines are broken then this column x-coord #hpos# - Real hpos; - - - /****************************************************************/ - - void add(const Item*i); - - Interval width() const; - ~PCol(); - PCol(PCol * parent); - - /// which col comes first? - static int compare(const PCol &c1, const PCol &c2); - /** - signed compare on columns. - - return < 0 if c1 < c2. - */ - - void OK() const; - void set_breakable(); - void print()const; -}; -/** - This is a class to address items vertically. It contains the data for: - \begin{itemize} - \item - unbroken score - \item - broken score - \item - the linespacing problem - \end{itemize} - */ - -#include "compare.hh" -instantiate_compare(const PCol &, PCol::compare); - - -/// ideal spacing between two columns -struct Idealspacing { - - /// the ideal distance - Real space; - - /// Hooke's constant: how strong are the "springs" attached to columns - Real hooke; - - /// the two columns - const PCol *left, *right; - - void print()const; - void OK() const ; - Idealspacing(const PCol *left,const PCol *right); -}; - -#endif diff --git a/proto.hh b/proto.hh deleted file mode 100644 index 268eda6b53..0000000000 --- a/proto.hh +++ /dev/null @@ -1,90 +0,0 @@ -/* - proto.hh -- part of LilyPond - - (c) 1996 Han-Wen Nienhuys -*/ - -#ifndef PROTO_HH -#define PROTO_HH -#include "real.hh" - -class Line_of_score; -class Line_of_staff; -class PCol; -class PStaff; -class Staff; -class Staff_column; -class Score; -class Score_column; -class Voice; -class Voice_element; -class Voicegroup; -class Request; -class Command; -class Request; -class Stem_req; -class Span_req; -class Slur_req; -class Decresc_req; -class Cresc_req; -class Bracket_req; -class Script_req; -class Rest_req; -class Note_req; -class Lyric_req; -class Chord; -class Absdynamic_req; -struct Offset; -struct Interval; -struct Box; -struct PCol; -struct Idealspacing; -struct Spanner; -struct Item; -struct Line_of_staff; -struct Colinfo; -struct Linestaff; -struct Atom; -struct Molecule; -struct PScore; -struct Request; -struct Note_req; -struct Lyric_req; -struct Script_req; -struct Rest_req; -struct Rhythmic_req; -struct Chord; -struct Stem_req; -struct Span_req; -struct Beam_req; -struct Bracket_req; -struct Slur_req; -struct Dynamic; -struct Cresc_req; -struct Decresc_req; -struct Absdynamic_req; -struct Score_column; -struct Score; -struct Staff_column; -struct Staff; -struct Command; -struct Symbol; -struct Output; -struct Text_gob; -struct Voice; -struct Voicegroup; -struct Voice_element; -struct String; -struct Tex_stream; -struct Identifier; -struct Keyword; -class Mixed_qp; -class Paperdef; -class Score_commands; -class Parametric_symbol; -struct Lookup; -struct Symtables; -struct Symtable; - -#endif // PROTO_HH - diff --git a/pscore.cc b/pscore.cc deleted file mode 100644 index 3f6f289d26..0000000000 --- a/pscore.cc +++ /dev/null @@ -1,174 +0,0 @@ -// utility functions for PScore -#include "debug.hh" -#include "paper.hh" -#include "molecule.hh" -#include "dimen.hh" -#include "line.hh" -#include "pscore.hh" -#include "tstream.hh" - -void -PScore::clean_cols() -{ - for (PCursor c(cols); c.ok(); ) - if (!c->used) { - c.del(); - } else - c++; -} - - -void -PScore::add(PStaff *s) -{ - staffs.bottom().add(s); -} - -void -PScore::typeset_item(Item *i, PCol *c, PStaff *s, int breakstat) -{ - assert(c && i && s); -// assert(!breakstat != 4 || c->breakable() ); - if (breakstat == 0) { - typeset_item(i, c->prebreak, s); - return; - } - - if (breakstat == 2) { - typeset_item(i, c->postbreak, s); - return; - } - if (c->daddy && c == c->daddy->prebreak) { // makeshift. - Interval iv (i->width()); - if (!iv.empty()) { - svec col_its (select_items(s, c)); - for (int j =0; j < col_its.sz(); j++) - col_its[j]->output->translate(Offset(-iv.length(),0)); - i->output->translate (Offset(-iv.max, 0)); - } - } - its.bottom().add(i); - s->add(i); - c->add(i); - i->preprocess(); -} - -void -PScore::add_line(svec curline, svec config) -{ - Line_of_score *p = new Line_of_score(curline,this); - lines.bottom().add(p); - for (int i=0; i < curline.sz(); i++){ - PCol *c=(PCol *)curline[i]; // so, this isn't really const. - c->hpos= config[i]; - } -} - -Idealspacing* -PScore::get_spacing(PCol*l, PCol*r) -{ - assert(l!=r); - for (PCursor ic (suz); ic.ok(); ic++) { - if (ic->left == l && ic->right == r){ - return ic; - } - } - - Idealspacing*ip =new Idealspacing(l,r); - suz.bottom().add(ip); - - return ip; -} - -svec -PScore::find_breaks() const -{ - svec retval; - for (PCursor c(cols); c.ok(); c++) - if (c->breakable()) - retval.add(c); - - return retval; -} - -void -PScore::add(PCol *p) -{ - cols.bottom().add(p); -} - -PScore::PScore( Paperdef*p) -{ - paper_ = p; -} - -void -PScore::output(Tex_stream &ts) -{ - int l=1; - - for (PCursor lic(lines); lic.ok(); lic++) { - ts << "% line of score no. " << l++ <<"\n"; - ts << lic->TeXstring(); - if ((lic+1).ok()) - ts << "\\interscoreline\n"; - } -} - -svec -PScore::select_items(PStaff*ps , PCol*pc) -{ - svec ret; - assert(ps && pc); - for (PCursor ic(pc->its); ic.ok(); ic++){ - if (ic->pstaff_ == ps) - ret.add((Item*)(const Item*)ic); - } - return ret; -} - -void -PScore::OK()const -{ -#ifdef NDEBUG - for (PCursor cc(cols); cc.ok(); cc++) - cc->OK(); - for (PCursor ic(suz); ic.ok(); ic++) - ic->OK(); -#endif -} - -void -PScore::print() const -{ -#ifndef NPRINT - mtor << "PScore { paper "; - paper_->print(); - mtor << "\ncolumns: "; - for (PCursor cc(cols); cc.ok(); cc++) - cc->print(); - - mtor << "\nideals: "; - for (PCursor ic(suz); ic.ok(); ic++) - ic->print(); - mtor << "}\n"; -#endif -} - -void -PScore::preprocess() -{ -#if 0 - for (PCursor ic(its); ic.ok(); ic++){ - ic->preprocess(); - } -#endif -} - -void -PScore::postprocess() -{ - for (PCursor ic(its); ic.ok(); ic++){ - ic->postprocess(); - } -} diff --git a/pscore.hh b/pscore.hh deleted file mode 100644 index 91436b369e..0000000000 --- a/pscore.hh +++ /dev/null @@ -1,88 +0,0 @@ -// the breaking problem for a score. - -#ifndef PSCORE_HH -#define PSCORE_HH - - -#include "vray.hh" -#include "pcol.hh" -#include "pstaff.hh" - -/// all stuff which goes onto paper -struct PScore { - Paperdef *paper_; // indirection. - - /// the columns, ordered left to right - PointerList cols; - - /// the idealspacings, no particular order - PointerList suz; - - /// the staffs ordered top to bottom - PointerList staffs; - - /// all symbols in score. No particular order. - PointerList its; - - /// if broken, the different lines - PointerList lines; - - /// crescs etc; no particular order - PointerList spanners; - - /****************************************************************/ - - svec select_items(PStaff*, PCol*); - - /// before calc_breaking - void preprocess(); - - void calc_breaking(); - /** - calculate where the lines are to be broken. - - POST - - lines contain the broken lines. - */ - - /// after calc_breaking - void postprocess(); - - /// search all pcols which are breakable. - svec find_breaks() const; - - /// add a line to the broken stuff. Positions given in #config# - void add_line(svec curline, svec config); - - /// helper: solve for the columns in #curline#. - svec solve_line(svec curline) const; - - void add(PStaff *); - /// add item - void typeset_item(Item *, PCol *,PStaff*,int=1); - /// add to bottom of pcols - void add(PCol*); - /** - - */ - void output(Tex_stream &ts); - - Idealspacing* get_spacing(PCol *, PCol *); - /* - get the spacing between c1 and c2, create one if necessary. - */ - - - PCursor find_col(PCol *); - void clean_cols(); - void problem_OK()const ; - void OK()const ; - PScore(Paperdef*); - void print() const; -}; -/** notes, signs, symbols in a score can be grouped in two ways: - horizontally (staffwise), and vertically (columns). #PScore# - contains the items, the columns and the staffs. - */ -#endif diff --git a/pstaff.cc b/pstaff.cc deleted file mode 100644 index 255fceeadd..0000000000 --- a/pstaff.cc +++ /dev/null @@ -1,14 +0,0 @@ -#include "pstaff.hh" - -PStaff::PStaff(PScore*ps) -{ - pscore_=ps; - stafsym = 0; -} - -void -PStaff::add(Item *i ) -{ - its.bottom().add(i); - i->pstaff_ = this; -} diff --git a/pstaff.hh b/pstaff.hh deleted file mode 100644 index bf33c6b437..0000000000 --- a/pstaff.hh +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef PSTAFF_HH -#define PSTAFF_HH - -#include "plist.hh" -#include "item.hh" -#include "symbol.hh" - -/// items grouped vertically. -struct PStaff { - Parametric_symbol *stafsym; - PScore * pscore_; - - virtual Symbol get_stafsym(Real width)const=0; // maybe overkill - - List spans; - List its; - - void add(Item*i); - PStaff(PScore*); - virtual ~PStaff() {} -}; - -#endif diff --git a/qlp.cc b/qlp.cc deleted file mode 100644 index 3dd8e4227e..0000000000 --- a/qlp.cc +++ /dev/null @@ -1,147 +0,0 @@ -#include "debug.hh" -#include "const.hh" -#include "qlp.hh" -#include "choleski.hh" - -void -Mixed_qp::add_equality_cons(Vector , double ) -{ - assert(false); -} - -void -Mixed_qp::add_fixed_var(int i, Real r) -{ - eq_cons.add(i); - eq_consrhs.add(r); -} - -void -Ineq_constrained_qp::add_inequality_cons(Vector c, double r) -{ - cons.add(c); - consrhs.add(r); -} - -Ineq_constrained_qp::Ineq_constrained_qp(int novars): - quad(novars), - lin(novars) -{ -} - -void -Ineq_constrained_qp::OK() const -{ -#ifndef NDEBUG - assert(cons.sz() == consrhs.sz()); - Matrix Qdif= quad - quad.transposed(); - assert(Qdif.norm()/quad.norm() < EPS); -#endif -} - - -Real -Ineq_constrained_qp::eval (Vector v) -{ - return v * quad * v + lin * v + const_term; -} -/* - eliminate appropriate variables, until we have a Ineq_constrained_qp - then solve that. - - PRE - cons should be ascending - */ -Vector -Mixed_qp::solve(Vector start) const -{ - print(); - Ineq_constrained_qp pure(*this); - - for (int i= eq_cons.sz()-1; i>=0; i--) { - pure.eliminate_var(eq_cons[i], eq_consrhs[i]); - start.del(eq_cons[i]); - } - Vector sol = pure.solve(start); - for (int i= 0; i < eq_cons.sz(); i++) { - sol.insert( eq_consrhs[i],eq_cons[i]); - } - return sol; -} - -/* - assume x(idx) == value, and adjust constraints, lin and quad accordingly - */ -void -Ineq_constrained_qp::eliminate_var(int idx, Real value) -{ - Vector row(quad.row(idx)); - row*= value; - - quad.delete_row(idx); - - quad.delete_column(idx); - - lin.del(idx); - row.del(idx); - lin +=row ; - - for (int i=0; i < cons.sz(); i++) { - consrhs[i] -= cons[i](idx) *value; - cons[i].del(idx); - } -} - - - - -Mixed_qp::Mixed_qp(int n) - : Ineq_constrained_qp(n) -{ -} - -void -Mixed_qp::OK() const -{ -#ifndef NDEBUG - Ineq_constrained_qp::OK(); - assert(eq_consrhs.sz() == eq_cons.sz()); -#endif -} -void -Ineq_constrained_qp::print() const -{ -#ifndef NPRINT - mtor << "Quad " << quad; - mtor << "lin " << lin <<"\n"; - for (int i=0; i < cons.sz(); i++) { - mtor << "constraint["<= " << consrhs[i]; - mtor << "\n"; - } -#endif -} -void -Mixed_qp::print() const -{ -#ifndef NPRINT - Ineq_constrained_qp::print(); - for (int i=0; i < eq_cons.sz(); i++) { - mtor << "eq cons "< binding; - for (int i=0; i < cons.sz(); i++) { - Real R=cons[i] * sol- consrhs[i]; - assert(R> -EPS); - if (R < EPS) - binding.add(i); - } - // KKT check... - // todo -} diff --git a/qlp.hh b/qlp.hh deleted file mode 100644 index b539fe6b86..0000000000 --- a/qlp.hh +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef QLP_HH -#define QLP_HH - -#include "matrix.hh" - -/// inequality constrained quadratic program -class Ineq_constrained_qp { - friend class Active_constraints; - - svec cons; - svec consrhs; -public: - Matrix quad; - Vector lin; - Real const_term; - - /// - void assert_solution(Vector sol) const; - /** - use a KKT method to assert optimality of sol - */ - /// solve the problem using a projected gradient method - Vector solve(Vector start) const; - - int dim() const{ - return lin.dim(); - } - /** return the number of variables in the problem */ - /// - void add_inequality_cons(Vector c, double r); - /** - add a constraint - - - c*vars >= r - - PRE - c.dim() == dim(); - - */ - /// - Ineq_constrained_qp(int novars); - /** set up matrices to go with the problem. */ - - Real eval(Vector v); - /** - evaluate the quadratic function for input #v# - */ - - void eliminate_var(int idx, Real value); - void OK()const; - void print() const; - -}; - -/// Quadratic programming with mixed linear constraints -class Mixed_qp :public Ineq_constrained_qp { - svec eq_cons; - svec eq_consrhs; -public: - Mixed_qp(int n); - void OK() const; - void print() const; - - Vector solve(Vector start) const; - void add_fixed_var(int i , Real value); - - /// - void add_equality_cons(Vector c, double r); - /** - add a constraint, - - c*vars == r - - PRE - c.dim()==dim(); - */ - -}; -/** - problem definition of a quadratic optimisation problem with linear - inequality and equality constraints - - - x^T QUAD x /2 + b^T x -*/ - - -#endif diff --git a/qlpsolve.cc b/qlpsolve.cc deleted file mode 100644 index 13bd30e89b..0000000000 --- a/qlpsolve.cc +++ /dev/null @@ -1,255 +0,0 @@ -#include "qlpsolve.hh" -#include "const.hh" -#include "debug.hh" -#include "choleski.hh" - -const Real TOL=1e-2; // roughly 1/10 mm - -String -Active_constraints::status() const -{ - String s("Active|Inactive ["); - for (int i=0; i< active.sz(); i++) { - s += String(active[i]) + " "; - } - - s+="| "; - for (int i=0; i< inactive.sz(); i++) { - s += String(inactive[i]) + " "; - } - s+="]"; - - return s; -} - -void -Active_constraints::OK() { - H.OK(); - A.OK(); - assert(active.sz() +inactive.sz() == opt->cons.sz()); - assert(H.dim() == opt->dim()); - assert(active.sz() == A.rows()); - svec allcons; - - for (int i=0; i < opt->cons.sz(); i++) - allcons.add(0); - for (int i=0; i < active.sz(); i++) { - int j = active[i]; - allcons[j]++; - } - for (int i=0; i < inactive.sz(); i++) { - int j = inactive[i]; - allcons[j]++; - } - for (int i=0; i < allcons.sz(); i++) - assert(allcons[i] == 1); -} - -Vector -Active_constraints::get_lagrange(Vector gradient) -{ - Vector l(A*gradient); - - return l; -} - -void -Active_constraints::add(int k) -{ - // add indices - int cidx=inactive[k]; - active.add(cidx); - - inactive.swap(k,inactive.sz()-1); - inactive.pop(); - - Vector a( opt->cons[cidx] ); - // update of matrices - Vector Ha = H*a; - Real aHa = a*Ha; - if (ABS(aHa) > EPS) { - /* - a != 0, so if Ha = O(EPS), then - Ha * aH / aHa = O(EPS^2/EPS) - - if H*a == 0, the constraints are dependent. - */ - H -= Matrix(Ha , Ha)/(aHa); - - - /* - sorry, don't know how to justify this. .. - */ - Vector addrow(Ha/(aHa)); - A -= Matrix(A*a, addrow); - A.insert_row(addrow,A.rows()); - }else - WARN << "degenerate constraints"; -} - -void -Active_constraints::drop(int k) -{ - int q=active.sz()-1; - - // drop indices - inactive.add(active[k]); - active.swap(k,q); - A.swap_rows(k,q); - active.pop(); - - Vector a(A.row(q)); - if (a.norm() > EPS) { - /* - - */ - H += Matrix(a,a)/(a*opt->quad*a); - A -= A*opt->quad*Matrix(a,a)/(a*opt->quad*a); - }else - WARN << "degenerate constraints"; - Vector rem_row(A.row(q)); - assert(rem_row.norm() < EPS); - A.delete_row(q); -} - - -Active_constraints::Active_constraints(Ineq_constrained_qp const *op) - : A(0,op->dim()), - H(op->dim()), - opt(op) -{ - for (int i=0; i < op->cons.sz(); i++) - inactive.add(i); - Choleski_decomposition chol(op->quad); - H=chol.inverse(); -} - -/* Find the optimum which is in the planes generated by the active - constraints. - */ -Vector -Active_constraints::find_active_optimum(Vector g) -{ - return H*g; -} - -/****************************************************************/ - -int -min_elt_index(Vector v) -{ - Real m=INFTY; int idx=-1; - for (int i = 0; i < v.dim(); i++){ - if (v(i) < m) { - idx = i; - m = v(i); - } - assert(v(i) <= INFTY); - } - return idx; -} - -///the numerical solving -Vector -Ineq_constrained_qp::solve(Vector start) const -{ - Active_constraints act(this); - - - act.OK(); - - - Vector x(start); - Vector gradient=quad*x+lin; - - - Vector last_gradient(gradient); - int iterations=0; - - while (iterations++ < MAXITER) { - Vector direction= - act.find_active_optimum(gradient); - - mtor << "gradient "<< gradient<< "\ndirection " << direction<<"\n"; - - if (direction.norm() > EPS) { - mtor << act.status() << '\n'; - - Real minalf = INFTY; - - Inactive_iter minidx(act); - - - /* - we know the optimum on this "hyperplane". Check if we - bump into the edges of the simplex - */ - - for (Inactive_iter ia(act); ia.ok(); ia++) { - - if (ia.vec() * direction >= 0) - continue; - Real alfa= - (ia.vec()*x - ia.rhs())/ - (ia.vec()*direction); - - if (minalf > alfa) { - minidx = ia; - minalf = alfa; - } - } - Real unbounded_alfa = 1.0; - Real optimal_step = MIN(minalf, unbounded_alfa); - - Vector deltax=direction * optimal_step; - x += deltax; - gradient += optimal_step * (quad * deltax); - - mtor << "step = " << optimal_step<< " (|dx| = " << - deltax.norm() << ")\n"; - - if (minalf < unbounded_alfa) { - /* bumped into an edge. try again, in smaller space. */ - act.add(minidx.idx()); - mtor << "adding cons "<< minidx.idx()<<'\n'; - continue; - } - /*ASSERT: we are at optimal solution for this "plane"*/ - - - } - - Vector lagrange_mult=act.get_lagrange(gradient); - int m= min_elt_index(lagrange_mult); - - if (m>=0 && lagrange_mult(m) > 0) { - break; // optimal sol. - } else if (m<0) { - assert(gradient.norm() < EPS) ; - - break; - } - - mtor << "dropping cons " << m<<'\n'; - act.drop(m); - } - if (iterations >= MAXITER) - WARN<<"didn't converge!\n"; - - mtor << ": found " << x<<" in " << iterations <<" iterations\n"; - assert_solution(x); - return x; -} - -/** Mordecai Avriel, Nonlinear Programming: analysis and methods (1976) - Prentice Hall. - - Section 13.3 - - This is a "projected gradient" algorithm. Starting from a point x - the next point is found in a direction determined by projecting - the gradient onto the active constraints. (well, not really the - gradient. The optimal solution obeying the active constraints is - tried. This is why H = Q^-1 in initialisation) ) - - - */ - diff --git a/qlpsolve.hh b/qlpsolve.hh deleted file mode 100644 index 4d29bcc4a0..0000000000 --- a/qlpsolve.hh +++ /dev/null @@ -1,78 +0,0 @@ -#include "qlp.hh" -#include "matrix.hh" - - -class Active_constraints { - friend class Inactive_iter; - - - Matrix A,H; - svec active; - svec inactive; // actually this is a set, not an array. - const Ineq_constrained_qp *opt; - -public: - String status()const; - - Vector vec(int k) const { return opt->cons[k]; } - Real rhs(int k) const { return opt->consrhs[k]; } - - /// drop constraint - void drop (int k); - /** drop constraint k from the active set. k is the index of the - constraint in #active# - - */ - - /// add constraint j - void add(int j); - /** - add constraint j to the active set j is the index of the - constraint in #inactive# - */ - - /// exchange in and out. - void exchange(int in, int out) { add(in); drop (out); } - - /// - Vector find_active_optimum(Vector g); - - /// get lagrange multipliers. - Vector get_lagrange(Vector v); - - Active_constraints(Ineq_constrained_qp const *op); - /** construct: no constraints active, n vars. Put the equalities - into the constraints. */ - - /// check invariants - void OK(); -}; - -/** - This class represents the set of active (binding) constraints - which can be active while the QLP algorithm is in a feasible - point. The active constraints are numbered. - If the constraints are of the form - - A^T*x >= b - - then the binding constraints are those where the >= is equality. - - */ - -/// -class Inactive_iter { - int j; - Active_constraints const* ac; -public: - Inactive_iter(Active_constraints const &c) { ac=&c; j=0; } - int idx() const { return j; } - void operator ++(int) { j++; } - int constraint_id() const { return ac->inactive[j]; } - Vector vec() const { return ac->vec(constraint_id()); } - Real rhs() const { return ac->rhs(constraint_id()); } - bool ok() const { return j < ac->inactive.sz(); } -}; -/** - loop through the inactive constraints. - */ diff --git a/request.cc b/request.cc deleted file mode 100644 index 35a9ae9718..0000000000 --- a/request.cc +++ /dev/null @@ -1,97 +0,0 @@ -#include "request.hh" -#include "debug.hh" - -#define VIRTUALCONS(T,R) R *T::clone() const { return new T(*this); } struct T -#define RCONS(T) VIRTUALCONS(T, Request) - -RCONS(Rest_req); -RCONS(Rhythmic_req); -RCONS(Stem_req); -RCONS(Note_req); - - -void -Request::print() const -{ -#ifndef NPRINT - mtor << "Req{ unknown }\n"; -#endif -} - -Request::Request(Voice_element*v) -{ - elt = v; -} - -Note_req::Note_req(Voice_element*v) - : Rhythmic_req(v) -{ - name = 'c'; - octave = 0; - accidental = 0; - forceacc = false; -} - -int -Note_req::height() const -{ - int s = name -'c'; - if (s < 0) - s+=7; - return s + octave*7; -} - -Rhythmic_req::Rhythmic_req(Voice_element*v) - :Request(v) -{ - balltype = 1; - dots = 0; -} - -void -Rhythmic_req::print() const -{ - mtor << "rhythmic: " << balltype ; - int d =dots; - while (d--) - mtor << '.'; - mtor<<"\n"; -} - -void -Note_req::print() const -{ - mtor << "note: " << name << " oct: "<< octave; - Rhythmic_req::print(); -} - -Request::Request() -{ - elt = 0; -} - -void -Rest_req::print() const -{ - mtor << "rest, " ; - Rhythmic_req::print(); -} - -Real -wholes(int dur, int dots) -{ - Real f = 1.0/Real(dur); - Real delta = f; - - while (dots--) { - delta /= 2.0; - f += delta; - } - return f; -} - -Real -Rhythmic_req::duration() const { - return wholes( balltype,dots); -} - diff --git a/request.hh b/request.hh deleted file mode 100644 index 04664966b3..0000000000 --- a/request.hh +++ /dev/null @@ -1,223 +0,0 @@ -// LilyPond's second egg of columbus! -#ifndef REQUEST_HH -#define REQUEST_HH - -#include "glob.hh" -#include "string.hh" - -/// a voice element wants something printed -struct Request { - Voice_element*elt; // indirection. - - /****************/ - - virtual void print()const ; - virtual Note_req *note() {return 0;} - virtual Stem_req *stem() {return 0;} - virtual Rest_req *rest() {return 0;} - virtual Rhythmic_req*rhythmic() { return 0;} - Request(Voice_element*); - Request(); - virtual Real duration() const { return 0.0; } - virtual Request* clone() const =0; -}; - -/** - Any Voice_element can do a number of requests. A request is done - to the #Staff# which contains the #Voice_element#. The staff decides - whether to to honor the request, ignore it, or merge it with other - requests. Merging of requests is preferably done with other - requests done by members of the same voicegroups (beams, brackets, stems) - - Please refer to the documentation of the Child classes of - #Request# for explanation of each request type. - - The result of a request will be an #Item# or a #Spanner#, which - will be put on a #PStaff#. Note that the #PStaff# and the original - #Staff# need not have anything in common. For example, the - ``double'' piano Staff could interpret commands which juggle - melodies across the left and right hand, and may put the result in - two five-line PStaffs (maybe with extra PStaffs to carry the dynamic - signs and any lyric. - - The class #Staff# should be thought as a container for the - #Voice#s, and an interpreter for #Request#s and #Command#s. - Different staffs can produce different outputs; a melodious voice - which is put into a percussion-Staff, will be typeset as the rythm of - that voice. - - After #Staff# made up her mind (Would #Staff# be a smart - name? How about #struct Susan {}# :-), the resultant items and - spanners are put on the PScore, and pointers to these items are - stored in the #Voice_element#. This construction enables the - beams/stems to look up the balls it has to connect to. */ - - -/// a request with a duration -struct Rhythmic_req : Request { - int balltype; - int dots; - - /****************/ - - Real duration() const; - Rhythmic_req(Voice_element*); - Rhythmic_req*rhythmic() { return this;} - void print ()const; - Request*clone() const; -}; - -/// Put a note of specified type, height, and with accidental on the staff. -struct Note_req : Rhythmic_req { - char name; - int octave; - int accidental; - bool forceacc; - - /****************/ - - // return height from central c (in halflines) - int height()const; - Note_req(Voice_element*v); - Note_req*note() { return this;} - virtual void print() const; - Request*clone() const; -}; -/** -Staff has to decide if the ball should be hanging left or right. This -influences the horizontal dimensions of a column, and this is why -request processing should be done before horizontal spacing. - -Other voices' frivolities may cause the need for accidentals, so this -is also for the Staff to decide. The Staff can decide on positioning -based on ottava commands and the appropriate clef. -*/ - - -///Put a rest on the staff. -struct Rest_req : Rhythmic_req { - void print()const; - Rest_req(Voice_element*v) : Rhythmic_req(v) { } - Rest_req * rest() { return this;} - Request*clone() const ; -}; -/** -Why a request? It might be a good idea to not typeset the rest, if the paper is too crowded. -*/ - -/// attach a stem to the noteball -struct Stem_req : Request { - /// 4,8,16, .. - int stem_number; - virtual Stem_req *stem() {return this;} - Stem_req(Voice_element*v, int s) : Request(v) { stem_number = s; } - Request*clone() const; -}; - - -#if 0 - -///Put a lyric above or below (?) this staff. -struct Lyric_req : Request { - String text; -}; - - -///Put a script above or below this ``note'' -struct Script_req : Request { - int orientation; - Symbol sym; -}; -/** -eg upbow, downbow. Why a request? These symbols may conflict with slurs and brackets, so this -also a request -*/ - - - - -///Draw a (Guitar) chord above or below this ``note'' -struct Chord : Request { - // don't know how this looks. -}; -/** -Why a request? -Because everything else is done in requests. -*/ - - -/// for absolute dynamics -enum Loudness { - FFF, FF, F, MF, MP, P, PP, PPP -} ; - -/// requests to start or stop something. -struct Span_req : Request { - /// should the spanner start or stop, or is it unwanted? - enum { - NOSPAN, START, STOP - } spantype ; -}; -/** - This type of request typically results in the creation of a #Spanner# -*/ - - -///Start / stop a beam at this note. -struct Beam_req : Span_req { - int nplet; -}; -/** Staff will have to combine this with the stem_request, since the - number of flags that a stem wants to carry will determine the - number of beams. if #nplet# is set, the staff will try to put an - appropriate number over the beam - - [what to do if the nplet fields of start and stop conflict?] - */ - -///Start / stop a slur or a bracket. -struct Bracket_req : Span_req { - int nplet; -}; -/** -Start/stop a bracket at this note. if #nplet# is set, the staff will -try to put an appropriate number over the bracket -*/ - -/// a slur -struct Slur_req : Span_req { - -}; - -/// helper in the hierarchy -struct Dynamic { - Real subtime; -}; -/** Each dynamic is bound to one note ( a crescendo spanning multiple - notes is thought to be made of two "dynamics": a start and a stop). - Dynamic changes can occur in a smaller time than the length of its - note, therefore fore each Dynamic request carries a time, measured - from the start of its note. - - This subfield would come in handy, if mpp96 was adapted for midi - support. - - Dynamic should have been derived from request, but I don't want to - fuss with virtual baseclasses. */ - -/// do a crescendo -struct Cresc_req : Span_req, Dynamic { - -}; - -/// do a decrescendo -struct Decresc_req : Span_req, Dynamic { - -}; - -/// do a dynamic like "fff" or "mp" -struct Absdynamic_req : Request, Dynamic { - Loudness loudness; -}; -#endif -#endif diff --git a/rhythmstaff.cc b/rhythmstaff.cc deleted file mode 100644 index 98d17d522c..0000000000 --- a/rhythmstaff.cc +++ /dev/null @@ -1,76 +0,0 @@ -#include "molecule.hh" -#include "notehead.hh" -#include "stem.hh" -#include "linestaff.hh" -#include "rhythmstaff.hh" -#include "paper.hh" -#include "sccol.hh" - - -void -Rhythmic_staff::set_output(PScore*ps) -{ - theline = new Linestaff(1,ps); - Simple_staff::set_output(ps); -} - - -void -Rhythmic_column::typeset_command(Command *com, int breakst) -{ - Item *i =new Item; - Molecule*m = create_command_mol(com); - i->output=m; - m->translate(Offset(0, - -staff_->score_->paper_->standard_height()/2)); - typeset_item(i, breakst); -} - -void -Rhythmic_column::typeset_req(Request *rq) -{ - 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); -} - -void -Rhythmic_column::typeset_stem(Stem_req*rq) -{ - Stem * s = new Stem(0); - s->minnote = s->maxnote = 0; - s->flag = rq->stem_number; - typeset_item(s); -} - -/* - creation - */ -Staff * -get_new_rhythmstaff() -{ - return new Rhythmic_staff; -} - - -Staff_column* -Rhythmic_staff::create_col(Score_column*s) -{ - return new Rhythmic_column(s,this); -} - -Rhythmic_staff* -Rhythmic_staff::clone() const -{ - return new Rhythmic_staff(*this); -} diff --git a/rhythmstaff.hh b/rhythmstaff.hh deleted file mode 100644 index 130f6483b9..0000000000 --- a/rhythmstaff.hh +++ /dev/null @@ -1,36 +0,0 @@ -/* - rhythmstaf.hh -- part of LilyPond - - (c) 1996 Han-Wen Nienhuys -*/ - -#ifndef RHYTHMSTAF_HH -#define RHYTHMSTAF_HH - -#include "simplestaff.hh" - -/// all notes on one line -struct Rhythmic_staff : public Simple_staff -{ - // Rhythmic_staff(); - Staff_column * create_col(Score_column*); - virtual void set_output(PScore *); - virtual Rhythmic_staff*clone()const; -}; - -/// this does the typesetting -struct Rhythmic_column : public Simple_column { - virtual void typeset_req(Request *rq); - virtual void typeset_stem(Stem_req *rq); - virtual void typeset_command(Command *, int brs); - - -// virtual void typeset_item(Item *rq, int=1); - Rhythmic_column(Score_column*s,Simple_staff*rs) : - Simple_column(s,rs) { } -// virtual Rhythmic_column*clone()const; -}; - -#endif // RHYTHMSTAF_HH - - diff --git a/sccol.cc b/sccol.cc deleted file mode 100644 index 1dfc8f2176..0000000000 --- a/sccol.cc +++ /dev/null @@ -1,28 +0,0 @@ -#include "sccol.hh" -#include "debug.hh" - -Score_column::Score_column(Real w) -{ - when = w; - pcol = new PCol(0); - musical = false; -} - -bool -Score_column::used() { - return pcol->used; -} - -void -Score_column::print() const -{ -#ifndef NPRINT - mtor << "Score_column { mus "<< musical <<" at " << when<<'\n'; - mtor << "durations: ["; - for (int i=0; i < durations.sz(); i++) - mtor << durations[i] << " "; - mtor << "]\n"; - pcol->print(); - mtor << "}\n"; -#endif -} diff --git a/sccol.hh b/sccol.hh deleted file mode 100644 index 21a341d17f..0000000000 --- a/sccol.hh +++ /dev/null @@ -1,45 +0,0 @@ -/* - sccol.hh -- part of LilyPond - - (c) 1996 Han-Wen Nienhuys -*/ - -#ifndef SCCOL_HH -#define SCCOL_HH -#include "pcol.hh" - - -struct Score_column { - PCol * pcol; - svec durations; - Real when; - - /// - bool musical; - - - Score_column(Real when); - - static int compare(Score_column & c1, Score_column &c2) { - return sgn(c1.when - c2.when); - } - void set_breakable() { - pcol->set_breakable(); - } - bool used(); - void print() const; -}; -/** - - When typesetting hasn't started on PScore yet, the columns which - contain data have a rhythmical position. Score_column is the type - with a rhythmical time attached to it. The calculation of - idealspacing is done with data in these columns. (notably: the - #durations# field) - - */ - -instantiate_compare(Score_column&, Score_column::compare); - -#endif // SCCOL_HH - diff --git a/scommands.cc b/scommands.cc deleted file mode 100644 index 8f86ff6fad..0000000000 --- a/scommands.cc +++ /dev/null @@ -1,261 +0,0 @@ -#include "scommands.hh" -#include "debug.hh" -#include "parseconstruct.hh" - -/* - maybe it's time for a "narrowing" cursor? - */ -PCursor -Score_commands::first(Real w) -{ - PCursor pc(*this); - while (pc.ok() && pc->when < w) - pc++; - - return pc; -} - -PCursor -Score_commands::last_insertion(Real w) -{ - PCursor pc(*this); - while (pc.ok() && pc->when <= w) - pc++; - return pc; -} - -void -Score_commands::add_seq(svec com) -{ - if (!com.sz()) - return; - Real when = com[0].when; - - PCursor pc(last_insertion(when)); - for (int i = 0; i < com.sz(); i++) { - Command *c = new Command(com[i]); - assert(com[i].when == when); - if (!pc.ok()) - pc.add(c); - else - pc.insert(c); - } -} - -void -Score_commands::set_breakable(Real when) -{ - bool found_typeset(false); - PCursor cc = first(when); - for (; cc.ok() && cc->when == when; cc++) { - if (cc->isbreak()) - return; - if (cc->code == TYPESET) - found_typeset=true; - } - - assert(!found_typeset); - - svec seq; - Command k(when); - k.code = BREAK_PRE; - seq.add(k); - k.code = BREAK_MIDDLE; - seq.add(k); - k.code = BREAK_POST; - seq.add(k); - k.code = BREAK_END; - seq.add(k); - - add_seq(seq); -} -bool -Score_commands::is_breakable(Real w) -{ - PCursor cc = first(w); - for (; cc.ok() && cc->when == w; cc++) { - if (cc->isbreak()) - return true; - } - return false; -} - -void -Score_commands::insert_between(Command victim, PCursor firstc, - PCursor last) -{ - assert(last->when==firstc->when); - PCursor c(firstc+1); - while (c != last) { // hmm what if !last.ok()? - if (victim.priority > c->priority) { - c.insert(new Command(victim)); - return; - } - c++; - } - last.insert(new Command(victim)); - -} -void -Score_commands::add_command_to_break(Command pre, Command mid,Command post) -{ - Real w = pre.when; - PCursor c ( first(w)), f(c), l(c); - - while (!c->isbreak()) - c++; - f = c++; - while (!c->isbreak()) - c++; - l = c++; - - insert_between(pre, f, l); - f = l; - while (!c->isbreak()) - c++; - l = c++; - insert_between(mid, f, l); - f = l; - while (!c->isbreak()) - c++; - l = c++; - insert_between(post, f, l); - assert(l.ok() && l->when ==w && l->code == BREAK_END); -} - -void -Score_commands::parser_add(Command *c) -{ - bottom().add(c); -} - -void -Score_commands::process_add(Command c) -{ - bool encapsulate =false; - Real w = c.when; - Command pre(w); - Command mid(w); - Command post(w); - - - if (c.code == TYPESET) { - if (c.args[0] == "BAR") { - set_breakable(w); - encapsulate = true; - mid = c; - pre = c; - } - if (c.args[0] == "METER" && is_breakable(w)) { - encapsulate = true; - mid = c; - pre = c; - post =c; - } - } - - if (encapsulate) - add_command_to_break(pre, mid, post); - else { - svec seq; - seq.add(c); - add_seq(seq); - } -} - -/* - first and last column should be breakable. - Remove any command past the last musical column. - */ -void -Score_commands::clean(Real l) -{ - assert(l>0); - if (!is_breakable(0.0)) { - Command c(0.0); - c.code = TYPESET; - c.args.add("BAR"); - c.args.add("empty"); - process_add(c); - } - - PCursor bot(bottom()); - - while (bot.ok() && bot->when > l) { - mtor <<"removing "; - bot->print(); - bot.del(); - bot = bottom(); - } - - if (!is_breakable(l)) { - Command c(l); - c.code = TYPESET; - c.args.add("BAR"); - c.args.add("||"); - process_add(c); - } - OK(); -} - -void -Score_commands::OK() const -{ - for (PCursor cc(*this); cc.ok() && (cc+1).ok(); cc++) { - assert(cc->when <= (cc+1)->when); - if (cc->when == (cc+1)->when && !cc->isbreak() && !(cc+1)->isbreak()) - assert(cc->priority >= (cc+1)->priority); - } -} - -void -Score_commands::print() const -{ - for (PCursor cc(*this); cc.ok() ; cc++) { - cc->print(); - } -} - -Score_commands* -Score_commands::parse(Real l) const -{ - Score_commands*nc = new Score_commands; - int beats_per_meas=4; - Real measlen = 1.0; // 4/4 by default - - Real inbar=0.0; - int barcount=0; - Real wholes=0.0; - Real stoppos=0.0; - - { - Command c(0.0); - c.code = TYPESET; - c.args.add("BAR"); - c.args.add("empty"); - nc->process_add(c); - } - for (PCursor cc(*this); cc.ok() && cc->when <= l; cc++) { - assert (cc->code==INTERPRET); - if (cc->args[0] == "METER") { - beats_per_meas=cc->args[1].value(); - int one_beat =cc->args[2].value (); - measlen = beats_per_meas/Real(one_beat); - nc->process_add(*get_meter_command(wholes,beats_per_meas, one_beat)); - } - if (cc->args[0] == "SKIP") { - stoppos = wholes + cc->args[1].value() * measlen + cc->args[2].fvalue(); - wholes += (measlen-inbar); // skip at least 1 measure - barcount++; - while (wholes <= stoppos) { - nc->process_add(*get_bar_command(wholes)); // liek - wholes += measlen; - barcount ++; - } - wholes = stoppos; - //something - } - } - - return nc; -} diff --git a/scommands.hh b/scommands.hh deleted file mode 100644 index 9106f2bfcc..0000000000 --- a/scommands.hh +++ /dev/null @@ -1,33 +0,0 @@ -/* - lilypond, (c) 1996 Han-Wen Nienhuys -*/ -#ifndef SCOMMANDS_HH -#define SCOMMANDS_HH - -#include "proto.hh" -#include "command.hh" -#include "vray.hh" -#include "plist.hh" - -struct Score_commands : public PointerList { - void process_add(Command); - Score_commands*parse(Real last)const; - void parser_add(Command*); - void add_seq(svec); - void clean(Real last); - void set_breakable(Real when); - bool is_breakable(Real w); - PCursor last_insertion(Real w); - PCursor first(Real w); - void add_command_to_break(Command pre, Command mid,Command post); - void OK() const; - void print() const; - Real last() const; - void insert_between(Command victim, PCursor firstc, - PCursor last); -}; -/** the list of commands in Score. Put in a separate class, since it - otherwise clutters the methods of Score. */ - -#endif - diff --git a/score.cc b/score.cc deleted file mode 100644 index 1df13365f2..0000000000 --- a/score.cc +++ /dev/null @@ -1,224 +0,0 @@ -#include "scommands.hh" -#include "tstream.hh" -#include "score.hh" -#include "sccol.hh" -#include "pscore.hh" -#include "staff.hh" -#include "debug.hh" -#include "paper.hh" - -void -Score::set(Paperdef*p) -{ - delete paper_; - paper_ = p; -} - -void -Score::output(String s) -{ - OK(); - if (paper_->outfile=="") - paper_->outfile = s; - - *mlog << "output to " << paper_->outfile << "...\n"; - Tex_stream the_output(paper_->outfile); - pscore_->output(the_output); -} - - -void -Score::process() -{ - *mlog << "Processing ... "; - set(commands_->parse(last())); - commands_->print(); - - if (!paper_) - paper_ = new Paperdef; - - commands_->clean(last()); - - /// distribute commands to disciples - distribute_commands(); - - pscore_ = new PScore(paper_); - for (PCursor sc(staffs_); sc.ok(); sc++) { - sc->set_output(pscore_); - sc->process(); - } - - // do this after processing, staffs first have to generate PCols. - do_pcols(); - calc_idealspacing(); - clean_cols(); - OK(); - // print(); - - pscore_->preprocess(); - *mlog << "Calculating ... "; - pscore_->calc_breaking(); - pscore_->postprocess(); - - // TODO: calculate vertical structs - // TODO: calculate mixed structs. - *mlog << "\n"; -} - -// remove empty cols with no spacing attached. -/* should rethink ownership of cols - */ -void -Score::clean_cols() -{ - for (PCursor sc(staffs_); sc.ok(); sc++) - sc->clean_cols(); - - for (PCursor c(cols_); c.ok(); ) { - if (!c->pcol->used) { - mtor << "removing : "; - c->print(); - c.del(); - } else - c++; - } - - pscore_->clean_cols(); -} -/* this sux. We should have Score_column create the appropriate PCol. - Unfortunately, PCols don't know about their position. - */ -// todo -PCursor -Score::create_cols(Real w) -{ - Score_column* c1 = new Score_column(w); - Score_column* c2 = new Score_column(w); - - c1->musical = false; - c2->musical = true; - - PCursor scc(cols_); - - for (; scc.ok(); scc++) { - assert(scc->when != w); - if (scc->when > w) - break; - } - - if (!scc.ok()) { - cols_.bottom().add(c1); - cols_.bottom().add(c2); - scc = cols_.bottom(); - scc --; - } else { - scc.insert(c1); - scc.insert(c2); - scc -= 2; - } - return scc; -} - -Score_column* -Score::find_col(Real w,bool mus) -{ - PCursor scc(cols_); - for (; scc.ok(); scc++) { - if (scc->when == w && scc->musical == mus) - return scc; - if (scc->when > w) - break; - } - scc = create_cols(w); - if (mus) - scc++; - return scc; -} - -void -Score::distribute_commands(void) -{ - for (PCursor sc(staffs_); sc.ok(); sc++) { - sc->add_commands(*commands_); - } -} -void -Score::add(Staff*s) -{ - s->score_ = this; - staffs_.bottom().add(s); -} - - -void -Score::do_pcols() -{ - PCursor sc(cols_); - for (; sc.ok(); sc++) { - pscore_->add(sc->pcol); - } -} -Real -Score::last() const -{ - Real l = 0; - for (PCursor stc(staffs_); stc.ok(); stc++) { - l = MAX(l, stc->last()); - } - return l; -} - -void -Score::OK() const -{ -#ifndef NDEBUG - for (PCursor sc(staffs_); sc.ok(); sc++) { - sc->OK(); - assert(sc->score_ == this); - } - staffs_.OK(); - cols_.OK(); - for (PCursor cc(cols_); cc.ok() && (cc+1).ok(); cc++) { - assert(cc->when <= (cc+1)->when); - } - commands_->OK(); -#endif -} - - -void -Score::print() const -{ -#ifndef NPRINT - mtor << "score {\n"; - for (PCursor sc(staffs_); sc.ok(); sc++) { - sc->print(); - } - for (PCursor sc(cols_); sc.ok(); sc++) { - sc->print(); - } - commands_->print(); - mtor << "}\n"; -#endif -} - -Score::Score() -{ - pscore_=0; - paper_ = 0; - commands_ = new Score_commands; -} - -Score::~Score() -{ - delete pscore_; - delete commands_; - delete paper_; -} - -void -Score::set(Score_commands*c) -{ - delete commands_; - commands_ = c; -} diff --git a/score.hh b/score.hh deleted file mode 100644 index 176d7fa47a..0000000000 --- a/score.hh +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SCORE_HH -#define SCORE_HH -#include "vray.hh" -#include "proto.hh" -#include "plist.hh" - - -/// the total music def of one movement -struct Score { - /// paper_, staffs_ and commands_ form the problem definition. - Paperdef *paper_; - PointerList staffs_; - Score_commands *commands_; - - /// "runtime" fields for setting up spacing - PointerList cols_; - PScore *pscore_; - - /****************************************************************/ - - /// construction - void add_staff(Staff *st); - void set(Paperdef*); - Score(); - ~Score(); - void add(Staff*); - void set(Score_commands*); - - - void OK() const; - Score_column *find_col(Real,bool); - void process(); - void output(String fn); - PCursor create_cols(Real); - void print() const; - Real last() const; - -private: - void do_pcols(); - void clean_cols(); - void distribute_commands(); - void do_connect(PCol *c1, PCol *c2, Real d); - void connect_nonmus(PCol* c1, PCol *c2, Real d); - /// add #Idealspacings# to #pscore_# - void calc_idealspacing(); - /** add the score wide commands (bars, breaks) to each staff so - they can process (typeset) them if needed */ -}; -/** - - */ -#endif diff --git a/scores.cc b/scores.cc deleted file mode 100644 index 04efd6e4b1..0000000000 --- a/scores.cc +++ /dev/null @@ -1,34 +0,0 @@ -#include "main.hh" -#include "score.hh" -#include "string.hh" - -static svec sv; - -static String outfn="lelie.uit"; - -// todo: check we don't overwrite default output. - -void -do_scores() -{ - for (int i=0; i < sv.sz(); i++) { - sv[i]->process(); - sv[i]->output(outfn); - delete sv[i]; - sv[i] =0; - } -} - -void -add_score(Score * s) -{ - sv.add(s); -} - - -void -set_default_output(String s) -{ - outfn = s; -} - diff --git a/simpleprint.cc b/simpleprint.cc deleted file mode 100644 index b069978dce..0000000000 --- a/simpleprint.cc +++ /dev/null @@ -1,75 +0,0 @@ -#include "lookupsyms.hh" -#include "request.hh" -#include "pscore.hh" -#include "paper.hh" -#include "simplestaff.hh" -#include "molecule.hh" -#include "sccol.hh" - -Molecule * -Simple_column::create_req_mol(Request *rq) -{ - assert(rq->rest()); - Symbol s; - int dots=0; - if (rq->rest()) - s = staff_->paper()->lookup_->rest(rq->rest()->balltype); - - if (rq->rhythmic()) - dots=rq->rhythmic()->dots; - - - Molecule *m = new Molecule(Atom(s)); - if (dots) { - Symbol d = staff_->paper()->lookup_->dots(dots); - Molecule dm; - dm.add(Atom(d)); - m->add_right(dm); - } - return m; -} - -Molecule * -Simple_column::create_command_mol(Command *com) -{ - Symbol s; - - if (com -> args[0] == "BAR" ) { - s = staff_->paper()->lookup_->bar(com->args[1]); - } else if (com->args[0] == "METER") { - Parametric_symbol *p = staff_->paper()->lookup_->meter("general"); - svec arg( com->args); - arg.del(0); - s = p->eval(arg); - } else - assert(false); - - Molecule * m =new Molecule(Atom(s)); - { - Interval wid; - svec sv(staff_->pscore_-> - select_items(staff_->theline, score_column->pcol)); - for (int j=0; joutput->extent().x); - } - if (!wid.empty()) - m->translate(Offset(wid.max,0)); - } - - return m; -} - -void -Simple_column::typeset_item(Item *i, int breakst) -{ - // ugh - staff_->pscore_->typeset_item(i, score_column->pcol, - staff_->theline,breakst); -} - -void -Simple_staff::set_output(PScore* ps ) -{ - pscore_ = ps; - pscore_->add(theline); -} diff --git a/simplestaff.cc b/simplestaff.cc deleted file mode 100644 index 97250b48cb..0000000000 --- a/simplestaff.cc +++ /dev/null @@ -1,91 +0,0 @@ -#include "request.hh" -#include "debug.hh" -#include "staff.hh" -#include "command.hh" -#include "simplestaff.hh" -#include "sccol.hh" - - - - -Simple_column::Simple_column(Score_column*s, Simple_staff *rs) - : Staff_column(s) -{ - the_note = 0; - stem_ = 0; - staff_ = rs; -} - -Simple_staff::Simple_staff() -{ - theline = 0; -} - -void -Simple_column::process_commands( ) -{ - int breakstat = BREAK_END - BREAK_PRE; - for (int i = 0 ; i < s_commands.sz(); i++) { - Command *com = s_commands[i]; - switch (com->code){ - case INTERPRET: - break; - case BREAK_PRE: - case BREAK_MIDDLE: - case BREAK_POST: - case BREAK_END: - score_column->set_breakable(); - breakstat = com->code- BREAK_PRE; - break; - - case TYPESET: - typeset_command ( com , breakstat); - break; - default : - break; - } - } -} -/** - accept: - - BREAK: all - TYPESET: bar, meter, - - */ - - - -void -Simple_column::process_requests() -{ - for (int i = 0 ; i < v_elts.sz(); i ++) - for (PCursor rqc(v_elts[i]->reqs); rqc.ok(); rqc++) { - Request *rq= rqc; - if (rq->rhythmic()){ - if (the_note){ - WARN << "too many notes.\n"; - } - the_note = rq; - - } - if (rq->stem()) { - stem_ = rq->stem(); - } - - } -} - -void -Simple_staff::grant_requests() -{ - for (PCursor cc(cols); cc.ok(); cc++) { - Simple_column *rp = (Simple_column*)*cc; - if (rp->the_note) - rp->typeset_req( rp->the_note); - if (rp->stem_) - rp->typeset_stem(rp->stem_->stem()); - } -} - - diff --git a/simplestaff.hh b/simplestaff.hh deleted file mode 100644 index c965765adb..0000000000 --- a/simplestaff.hh +++ /dev/null @@ -1,61 +0,0 @@ -/* - simplestaff.hh -- part of LilyPond - - (c) 1996 Han-Wen Nienhuys -*/ - -#ifndef SIMPLESTAFF_HH -#define SIMPLESTAFF_HH - -#include "stcol.hh" -#include "staff.hh" -/* - mega-stupido staffs and cols: they do notes one at each moment. - */ - -struct Simple_staff; - -/// column of Simple_staff: store one request -struct Simple_column : Staff_column { - - Request *the_note; - Stem_req *stem_; - - Simple_staff* staff_; - - /****************/ - virtual void typeset_stem(Stem_req *rq)=0; - virtual void typeset_req(Request *rq)=0; - virtual void typeset_command(Command *, int brs)=0; - virtual void typeset_item(Item *, int=1); - - Molecule *create_command_mol(Command *com); - Molecule *create_req_mol(Request *rq); - void take_request(Request *rq); - - virtual void process_commands( ); - virtual void process_requests(); - - Simple_column(Score_column*s,Simple_staff*rs); -}; - - -/// Simple staff: one note at a time -struct Simple_staff : Staff { - /// indirection to the PStaff. - PStaff *theline; - - /****************/ - virtual void set_output(PScore *); - - void process_commands( PCursor &where); - void grant_requests(); -// virtual Staff*clone()const; - - Simple_staff(); -}; - -#endif // SIMPLESTAFF_HH - - - diff --git a/spanner.cc b/spanner.cc deleted file mode 100644 index be30c04659..0000000000 --- a/spanner.cc +++ /dev/null @@ -1,33 +0,0 @@ - -#include "spanner.hh" -#include "line.hh" - -#include "symbol.hh" -#include "molecule.hh" -#include "pcol.hh" - -String -Spanner::TeXstring() const -{ - assert(right->line); - Real w = left->hpos - right->hpos; - return strets->eval(w).tex; -} - -// todo. -Spanner * -Spanner::broken_at(const PCol *c1, const PCol *c2) const -{ - Spanner *sp = new Spanner(*this); - sp->left = c1; - sp->right = c2; - return sp; -} - -Spanner::Spanner() -{ - pstaff_=0; - strets=0; - left = right = 0; -} - diff --git a/spanner.hh b/spanner.hh deleted file mode 100644 index 1908d2f013..0000000000 --- a/spanner.hh +++ /dev/null @@ -1,34 +0,0 @@ -/* - spanner.hh -- part of LilyPond - - (c) 1996 Han-Wen Nienhuys -*/ - -#ifndef SPANNER_HH -#define SPANNER_HH -#include "proto.hh" - -/// a symbol which is attached between two columns. -struct Spanner { - const PCol *left, *right; - Parametric_symbol *strets; - PStaff * pstaff_; - /// clone a piece of this spanner. - virtual Spanner *broken_at(const PCol *c1, const PCol *c2) const; - /** - - PRE - c1 >= start, c2 <= stop - */ - /****************/ - 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 - is absolutely necessary for beams, since they have to adjust the - length of stems of notes they encompass. - - */ -#endif diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000000..65374e807e --- /dev/null +++ b/src/Makefile @@ -0,0 +1,8 @@ +default: + $(MAKE) -C .. + +dist: + ln Makefile $(mycc) $(othersrc) $(DDIR)/src + +TAGS: $(mycc) + etags -CT $(mycc) diff --git a/src/bar.cc b/src/bar.cc new file mode 100644 index 0000000000..bb66f2b777 --- /dev/null +++ b/src/bar.cc @@ -0,0 +1,18 @@ +#include "bar.hh" +#include "string.hh" +#include "molecule.hh" +#include "paper.hh" +#include "lookup.hh" + + +Bar::Bar( String t) +{ + type = t; +} +void +Bar::preprocess() +{ + Symbol s = paper()->lookup_->bar(type); + output = new Molecule(Atom(s)); +} + diff --git a/src/beam.cc b/src/beam.cc new file mode 100644 index 0000000000..49214c91f2 --- /dev/null +++ b/src/beam.cc @@ -0,0 +1,179 @@ +#include "beam.hh" +#include "debug.hh" +#include "symbol.hh" +#include "molecule.hh" +#include "leastsquares.hh" +#include "pcol.hh" +#include "stem.hh" +#include "paper.hh" +#include "lookup.hh" + + +struct Stem_info { + Real x; + Real idealy; + Real miny; + int no_beams; + + 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); + assert(miny <= idealy); + no_beams = s->flag; +} + +/****************/ + +Beam::Beam() +{ + slope = 0; + left_pos = 0.0; + dir =0; +} + +void +Beam::add(Stem*s) +{ + stems.bottom().add(s); + s->print_flag = false; +} + +void +Beam::set_default_dir() +{ + int dirs[2]; + dirs[0]=0; dirs[1] =0; + for (PCursor sc(stems); sc.ok(); sc++) { + sc->set_default_dir(); + dirs[(sc->dir+1)/2] ++; + } + dir = (dirs[0] > dirs[1]) ? -1 : 1; + for (PCursor sc(stems); sc.ok(); sc++) { + sc->dir = dir; + } +} + +void +Beam::solve_slope() +{ + svec sinfo; + for (PCursorsc(stems); sc.ok(); sc++) { + sc->set_default_extents(); + Stem_info i(sc); + sinfo.add(i); + } + Real leftx = sinfo[0].x; + Least_squares l; + for (int i=0; i < sinfo.sz(); i++) { + sinfo[i].x -= leftx; + l.input.add(Offset(sinfo[i].x, sinfo[i].idealy)); + } + + l.minimise(slope, left_pos); + Real dy = 0.0; + for (int i=0; i < sinfo.sz(); i++) { + Real y = sinfo[i].x * slope + left_pos; + Real my = sinfo[i].miny; + + if (my - y > dy) + dy = my -y; + } + left_pos += dy; + 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 +Beam::set_stemlens() +{ + PCursor s(stems); + Real x0 = s->hpos(); + for (; s.ok() ; s++) { + Real x = s->hpos()-x0; + s->set_stemend(left_pos + slope * x); + } +} + +void +Beam::calculate() +{ + assert(stems.size()>1); + if (!dir) + set_default_dir(); + + solve_slope(); + set_stemlens(); +} + +void +Beam::process() +{ + calculate(); + brew_molecule(); +} + + +// todo. +Spanner * +Beam::broken_at(const PCol *, const PCol *) const +{ + return new Beam(*this); +} + +void +Beam::preprocess() +{ + left = (*stems.top()) ->pcol_; + right = (*stems.bottom())->pcol_; +} + +Interval +Beam::height() const +{ + return output->extent().y; +} + +Interval +Beam::width() const +{ + Beam * me = (Beam*) this; // ugh + return Interval( (*me->stems.top()) ->hpos(), + (*me->stems.bottom()) ->hpos() ); +} + +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); + + Real dx = width().min -left->hpos; + a.translate(Offset(dx,left_pos*inter)); + output = new Molecule(a); +} + +void +Beam::print()const +{ + mtor << "Beam, slope " < s) +{ + assert(s.sz() == 4); + x.min = s[0]; + x.max = s[1]; + y.min = s[2]; + y.max = s[3]; +} + +Box::Box() +{ +} + +Box::Box(Interval ix, Interval iy) +{ + x = ix; + y = iy; +} + diff --git a/src/break.cc b/src/break.cc new file mode 100644 index 0000000000..de9a704984 --- /dev/null +++ b/src/break.cc @@ -0,0 +1,135 @@ +/* + do calculations for breaking problem + + */ +#include "paper.hh" +#include "linespace.hh" +#include "debug.hh" +#include "scoreline.hh" +#include "pscore.hh" + +// construct an appropriate Spacing_problem and solve it. +svec +PScore::solve_line(svec curline) const +{ + Spacing_problem sp; + + sp.add_column(curline[0], true, 0.0); + for (int i=1; i< curline.sz()-1; i++) + sp.add_column(curline[i]); + sp.add_column(curline.last(), true, paper_->linewidth); + + // misschien moeven uit Spacing_problem? + for (PCursor i(suz); i.ok(); i++) { + sp.add_ideal(i); + } + svec the_sol=sp.solve(); + return the_sol; +} + +bool +PScore::feasible(svec curline) const +{ + Real l =0; + for (int i=0; i < curline.sz(); i++) + l +=curline[i]->width().length(); + return l < paper_->linewidth; +} + +void +PScore::problem_OK() const +{ + if (!cols.size()) + error("PScore::problem_OK(): Score does not have any columns"); + PCursor start(cols); + PCursor end (((PScore*)this)->cols.bottom()); + + assert(start->breakable()); + assert(end->breakable()); +} + +struct Col_configuration { + svec line; + svec config; + Real energy; + + Col_configuration() { + energy = INFTY; + } + void add(const PCol*c) { line.add(c);} + void setsol(svec sol) { + config = sol; + energy = config.last(); + config.pop(); + } + void print() const { +#ifndef NPRINT + mtor << "energy : " << energy << '\n'; + mtor << "line of " << config.sz() << " cols\n"; +#endif + } +}; + +/// wordwrap type algorithm +/* el stupido. This should be done more accurately: + + It would be nice to have a Dynamic Programming type of algorithm + similar to TeX's + + */ + +void +PScore::calc_breaking() +{ + OK(); + problem_OK(); + PCursor curcol(cols); + + svec breakpoints(find_breaks()); + assert(breakpoints.sz()>=2); + for (int i=0 ; i < breakpoints.sz() -1; ) { + Col_configuration minimum; + Col_configuration current; + + // do another line + PCol *post = breakpoints[i]->postbreak; + current.add( post); + curcol++; // skip the breakable. + i++; + + while (i < breakpoints.sz()) { + + // add another measure. + while(breakpoints[i] !=curcol){ + + current.add(curcol); + curcol++; + } + current.add(breakpoints[i]->prebreak ); + if (!feasible(current.line)) { + if (!minimum.line.sz()) + error("sorry, this measure is too long"); + break; + } + current.setsol(solve_line(current.line)); + current.print(); + + if (current.energy < minimum.energy) { + minimum = current; + } else { // we're one col too far. + i--; + while (curcol != breakpoints[i]) + curcol --; + + break; + } + + current.line.last()=breakpoints[i]; + curcol ++; + i++; + } + mtor << "Adding line, next breakpoint " << i << '\n'; + add_line(minimum.line, minimum.config); + } +} + diff --git a/src/calcideal.cc b/src/calcideal.cc new file mode 100644 index 0000000000..8099e0e4c7 --- /dev/null +++ b/src/calcideal.cc @@ -0,0 +1,65 @@ +#include "tstream.hh" +#include "score.hh" +#include "pscore.hh" +#include "staff.hh" +#include "paper.hh" +#include "sccol.hh" +#include "debug.hh" + + +void +Score::do_connect(PCol *c1, PCol *c2, Real d) +{ + Idealspacing*sp=pscore_->get_spacing(c1,c2); + + if (!sp->hooke){ + sp->hooke = 1.0; + sp->space =d; + } +} + +void +Score::connect_nonmus(PCol* c1, PCol *c2, Real d) +{ + if (c2->used && c1->used) { + do_connect(c1,c2,d); + + // alert! this is broken! + if (c1->breakable()) { + do_connect(c1->postbreak, c2,d); + } + if (c2->breakable()) { + do_connect(c1, c2->prebreak,d); + } + if (c1->breakable() &&c2->breakable()) { + do_connect(c1->postbreak, c2->prebreak,d); + } + } +} +/* this needs A LOT of rethinking. + + generate springs between columns. + */ +void +Score::calc_idealspacing() +{ + PCursor sc(cols_); + + for (; sc.ok(); sc++) { + if (sc->musical) + for (int i=0; i < sc->durations.sz(); i++) { + Real d = sc->durations[i]; + 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; + connect_nonmus(sc->pcol, c2, dist); + } + else if (sc->used()) { // ignore empty columns + PCol * c2 = find_col(sc->when,true)->pcol; + connect_nonmus(sc->pcol,c2,0.0); + } + } +} + + diff --git a/src/command.cc b/src/command.cc new file mode 100644 index 0000000000..23edf1ec36 --- /dev/null +++ b/src/command.cc @@ -0,0 +1,39 @@ +#include "string.hh" +#include "debug.hh" +#include "command.hh" + +bool +Command::isbreak()const +{ + return (code >= BREAK_PRE && code <= BREAK_END); +} + +Command::Command() +{ + code = NOP; + when = -1; + priority=0; +} + + + +Command::Command(Real w) +{ + code = NOP; + when = w; + priority=0; +} + +void +Command::print() const +{ +#ifndef NPRINT + mtor << "command at " << when << ", code " << code << " prio " << priority; + if (args.sz()) { + mtor<< " args: "; + for (int i = 0; i +#include +#include "debug.hh" +#include "dstream.hh" +#include "vector.hh" + +Dstream monitor(&cout,".dstreamrc"); +ostream * nulldev = new ofstream("/dev/null"); + + +/* + want to do a stacktrace . + */ +void +mynewhandler() +{ + cerr << "Out of free store memory. Aborting.. "<< flush; + assert(false); +} + + +void +debug_init() +{ + set_new_handler(&mynewhandler); + set_matrix_debug(monitor); +} diff --git a/src/dimen.cc b/src/dimen.cc new file mode 100644 index 0000000000..eb53756b45 --- /dev/null +++ b/src/dimen.cc @@ -0,0 +1,40 @@ +#include +#include "dimen.hh" +#include "debug.hh" +#include "string.hh" + +Real +parse_dimen(String dim) +{ + int i=dim.len()-1; + const char *s = dim; + while (i > 0 && (isspace(s[i]) || isalpha(s[i])) ){ + i--; + } + String unit(s + i+1); + return convert_dimen(dim.fvalue(), unit); +} + +const Real CM_TO_PT=72/2.54; + +Real +convert_dimen(Real quant, String unit) +{ + if (unit == "cm") + return quant * CM_TO_PT; + if (unit == "pt") + return quant; + if (unit == "mm") + return quant*CM_TO_PT/10; + if (unit == "in") + return quant * 72; + error ("unknown length unit: `" + unit+"'"); +} + +String +print_dimen(Real r) +{ + String s(r); + s += "pt "; + return s; +} diff --git a/src/getcommands.cc b/src/getcommands.cc new file mode 100644 index 0000000000..1f9362c59c --- /dev/null +++ b/src/getcommands.cc @@ -0,0 +1,58 @@ +#include "string.hh" +#include "parseconstruct.hh" +#include "command.hh" + +Command* +get_bar_command(Real w) +{ + Command*c = new Command; + c->when = w; + c->code = TYPESET; + c->args.add( "BAR"); + c->args.add( "|"); + c->priority = 100; + return c; +} + +Command * +get_meter_command(Real w, int n, int m) +{ + Command*c = new Command; + + c->when = w; + c->code = TYPESET; + c->args.add( "METER"); + c->args.add( n ); + c->args.add( m ); + c->priority = 50; // less than bar + return c; +} + +Command * +get_meterchange_command(int n, int m) +{ + Command*c = new Command; + + c->code = INTERPRET; + c->args.add( "METER"); + c->args.add( n ); + c->args.add( m ); + c->priority = 0; // more than bar + return c; +} + + +Command * +get_skip_command(int n, Real m) +{ + Command*c = new Command; + + c->code = INTERPRET; + c->args.add( "SKIP"); + c->args.add( n ); + c->args.add( m ); + c->priority = 0; // more than bar + return c; +} + + diff --git a/src/identifier.cc b/src/identifier.cc new file mode 100644 index 0000000000..024fe06486 --- /dev/null +++ b/src/identifier.cc @@ -0,0 +1,26 @@ +#include +#include "identifier.hh" +#include "staff.hh" +#include "lexer.hh" + + +Identifier::Identifier(String n) + :name (n) +{ + data = 0; +} + + +Identifier::~Identifier() +{ +} + +Staff_id::~Staff_id() +{ + delete staff(); +} + +Voice_id::~Voice_id() +{ + delete voice(); +} diff --git a/src/item.cc b/src/item.cc new file mode 100644 index 0000000000..914c924a99 --- /dev/null +++ b/src/item.cc @@ -0,0 +1,73 @@ +#include "pstaff.hh" +#include "pscore.hh" +#include "symbol.hh" +#include "molecule.hh" +#include "pcol.hh" + +void +Item::translate(Offset O) +{ + offset_ += O; +} + +void +Item::postprocess() +{ + // default: do nothing +} + + +void +Item::preprocess() +{ + // default: do nothing +} + +String +Item::TeXstring() const +{ + Item * me = (Item*) this; + output->translate(offset_); // ugh? + me ->offset_ = Offset(0,0); // URRGGH! + return output->TeXstring(); +} + +Interval +Item::width() const +{ + Interval i =output->extent().x ; + return i+=offset_.x; +} + +Interval +Item::height() const +{ + Interval i =output->extent().y; + return i+=offset_.y; +} + +Item::~Item() +{ + delete output; +} + +Item::Item() +{ + pcol_ = 0; + output = 0; + pstaff_ = 0; +} +void +Item::print() const +{ + assert(output); + output->print(); +} + +Paperdef* +Item::paper() const +{ + assert(pstaff_); + return pstaff_->pscore_->paper_; +} + diff --git a/src/keyword.cc b/src/keyword.cc new file mode 100644 index 0000000000..14903cfb61 --- /dev/null +++ b/src/keyword.cc @@ -0,0 +1,79 @@ +/* + keyword.cc -- keywords and identifiers + */ + +#include + +#include "glob.hh" +#include "lexer.hh" +//#include "mudobs.hh" +//#include "gram.hh" + +/* for the keyword table */ +struct Keyword_ent +{ + const char *name; + int tokcode; +}; + +struct Keyword_table +{ + Keyword_ent *table; + int maxkey; + Keyword_table(Keyword_ent *); + int lookup(const char *s) const; +}; + + +/* for qsort */ +int + tabcmp(const void * p1, const void * p2) +{ + return strcmp(((const Keyword_ent *) p1)->name, + ((const Keyword_ent *) p2)->name); +} + +Keyword_table::Keyword_table(Keyword_ent *tab) +{ + table = tab; + + /* count keywords */ + for (maxkey = 0; table[maxkey].name; maxkey++); + + /* sort them */ + qsort(table, maxkey, sizeof(Keyword_ent), tabcmp); +} + +/* + lookup with binsearch, return tokencode. +*/ +int +Keyword_table::lookup(const char *s)const +{ + int lo, + hi, + cmp, + result; + lo = 0; + hi = maxkey; + + /* binary search */ + do + { + cmp = (lo + hi) / 2; + + result = strcmp(s, table[cmp].name); + + if (result < 0) + hi = cmp; + else + lo = cmp; + } + while (hi - lo > 1); + if (!strcmp(s, table[lo].name)) + { + return table[lo].tokcode; + } else + return -1; /* not found */ +} + diff --git a/src/leastsquares.cc b/src/leastsquares.cc new file mode 100644 index 0000000000..1e1c91cee3 --- /dev/null +++ b/src/leastsquares.cc @@ -0,0 +1,25 @@ +#include "leastsquares.hh" + +void +Least_squares::minimise(Real &coef, Real &offset) +{ + Real sx = 0.0; + Real sy = 0.0; + Real sqx =0.0; + Real sxy = 0.0; + + for (int i=0; i < input.sz();i++) { + Real x=input[i].x; + Real y = input[i].y; + sx += x; + sy += y; + sqx += sqr(x); + sxy += x*y; + } + int N = input.sz(); + + + coef = (N * sxy - sx*sy )/(N*sqx - sqr(sx)); + offset = (sy - coef * sx)/N; + +} diff --git a/src/lexer.l b/src/lexer.l new file mode 100644 index 0000000000..1e3443e56e --- /dev/null +++ b/src/lexer.l @@ -0,0 +1,229 @@ +%{ // -*-Fundamental-*- + +#include +#include +#include "glob.hh" +#include "string.hh" + +#include "lexer.hh" +#include "keyword.hh" +#include "vray.hh" +#include "parser.hh" +#include "debug.hh" + +sstack include_stack; +static int last_print; +const int DOTPRINT=50; // every 50 lines dots +%} + +%option c++ +%option noyywrap +%option nodefault +%option yylineno +%option debug +%x notes +%x incl +%x quote + + +NOTECOMMAND \\{WORD} +OPTSIGN !? +NOTENAMEI A|B|C|D|E|F|G|As|Bes|Ces|Des|Es|Fes|Ges|Ais|Bis|Cis|Dis|Eis|Fis|Gis +NOTENAMEII a|b|c|d|e|f|g|as|bes|ces|des|es|fes|ges|ais|bis|cis|dis|eis|fis|gis +NOTENAMEIII Ases|Beses|Ceses|Deses|Eses|Feses|Geses|Aisis|Bisis|Cisis|Disis|Eisis|Fisis|Gisis +NOTENAMEIIII ases|beses|ceses|deses|eses|feses|geses|aisis|bisis|cisis|disis|eisis|fisis|gisis +RESTNAME r|s +NOTENAME {NOTENAMEI}|{NOTENAMEII}|{NOTENAMEIII}|{NOTENAMEIIII} +PITCH ['`]*{OPTSIGN}{NOTENAME} +DURNAME 1|2|4|8|16|32 +DURATION {DURNAME}\.* +FULLNOTE {PITCH}{DURATION}? +WORD [a-zA-Z][a-zA-Z0-9_]+ +REAL [0-9]+(\.[0-9]*)? + +%% + +\$ { + BEGIN(notes); return '$'; +} + +{NOTECOMMAND} { + String c = YYText() +1; + int l = lookup_keyword(c); + if (l == -1) { + String e("unknown NOTECOMMAND: \\"); + e += c; + yyerror(e); + } + return l; +} + +{RESTNAME} { + const char *s = YYText(); + yylval.string = new String (s); + mtor << "rest:"<< yylval.string; + return RESTNAME; +} +{PITCH} { + const char *s = YYText(); + yylval.string = new String (s); + mtor << "pitch:"<< *yylval.string; + return PITCH; +} +{DURATION} { + yylval.string = new String (YYText()); + return DURATION; +} +\| { +} +[:space:]+ { +} +[ \t\n]+ { +} +%.* { + +} +\$ { + BEGIN(INITIAL); return '$'; +} +[\[){] { /* parens () are NO mistake */ + yylval.c = YYText()[0]; + return OPEN_REQUEST_PARENS; +} +[\]()}] { /* parens () are NO mistake */ + yylval.c = YYText()[0]; + return CLOSE_REQUEST_PARENS; +} + +. { + String s("lexer error: illegal character found: " + String(YYText())); + yyerror(s); +} + +\" { + BEGIN(quote); +} +[^\"]* { + yylval.string = new String (YYText()); +} +\" { + BEGIN(INITIAL); + return STRING; +} + +<> { + if(!close_input()) + yyterminate(); +} +{WORD} { + int l = lookup_keyword(YYText()); + if (l != -1) + return l; + Identifier * id = lookup_identifier(YYText()); + if (id) { + yylval.id = id; + return IDENTIFIER; + } + String *sp = new String( YYText()); + mtor << "new id: " << *sp; + yylval.string=sp; + return NEWIDENTIFIER; +} + +{REAL} { + Real r; + int cnv=sscanf (YYText(), "%lf", &r); + assert(cnv == 1); + mtor << "token (REAL)" << r; + yylval.real = r; + return REAL; +} + +[\{\}\[\]\(\)] { + + mtor << "parens\n"; + return YYText()[0]; +} +[:=] { + char c = YYText()[0]; + mtor << "misc char" <set_debug( !monitor.silence("Lexer")); + } + + lexer->switch_streams(newin); +} + + +// pop the inputstack. +bool +close_input() +{ + + istream *closing= include_stack.pop(); + if (closing != &cin) + delete closing; + + cout << "]" << flush; + + if (include_stack.empty()) { + return false ; + } else + lexer->switch_streams(include_stack.top()); + return true; +} + +int +yylex() { + return lexer->yylex(); +} + +void +yyerror(const char *s) +{ + *mlog << "error in line " << lexer->lineno() << ": " << s << '\n'; + exit(1); +} + +void +kill_lexer() +{ + delete lexer; +} diff --git a/src/linespace.cc b/src/linespace.cc new file mode 100644 index 0000000000..6b16c9afab --- /dev/null +++ b/src/linespace.cc @@ -0,0 +1,264 @@ +#include +#include "linespace.hh" +#include "debug.hh" +#include "qlp.hh" +#include "unionfind.hh" + +const Real COLFUDGE=1e-3; +//#define COLFUDGE 1e-3 +bool +Spacing_problem::contains(const PCol *w) +{ + for (int i=0; i< cols.sz(); i++) + if (cols[i].pcol_ == w) + return true; + return false; +} + +int +Spacing_problem::col_id(const PCol *w)const +{ + for (int i=0; i< cols.sz(); i++) + if (cols[i].pcol_ == w) + return i; + assert(false); +} + +void +Spacing_problem::OK() const +{ +#ifndef NDEBUG + Union_find connected(cols.sz()); + svec fixed; + for (int i=0; i < ideals.sz(); i++) { + assert(ideals[i]->hooke > 0); + int l = col_id(ideals[i]->left); + int r = col_id(ideals[i]->right); + connected.connect(l,r); + } + for (int i = 0; i < cols.sz(); i++) + if (cols[i].fixed) + fixed.add(i); + for (int i = 0; i < cols.sz(); i++) { + bool c=false; + for (int j =0; j COLFUDGE) { + return false; + } + if (!i) + continue; + + Real mindist=cols[i-1].minright() + +cols[i].minleft(); + + // ugh... compares + Real dif =v(i) - v(i-1)- mindist; + bool b = (dif > - COLFUDGE); + + +#if 1 + if (!b) + return false; + +#else + mtor << "dif= "<fudge= "<< + b << "\n"; + + /* fucks up for unknown reasons */ + if (dif < -COLFUDGE) + return false; +#endif + + } + return true; +} + +bool +Spacing_problem::check_feasible() const +{ + Vector sol(try_initial_solution()); + return check_constraints(sol); +} + +// generate a solution which obeys the min distances and fixed positions +Vector +Spacing_problem::try_initial_solution() const +{ + int dim=cols.sz(); + Vector initsol(dim); + for (int i=0; i < dim; i++) { + if (cols[i].fixed) { + initsol(i)=cols[i].fixpos; + } else { + Real mindist=cols[i-1].minright() + +cols[i].minleft(); + assert(mindist >= 0.0); + initsol(i)=initsol(i-1)+mindist; + + //nog niet + //if (i>0) + // assert(initsol(i) > initsol(i-1)); + } + } + + return initsol; +} +Vector +Spacing_problem::find_initial_solution() const +{ + Vector v(try_initial_solution()); + assert(check_constraints(v)); + return v; +} +// generate the matrices +void +Spacing_problem::make_matrices(Matrix &quad, Vector &lin, Real &c) const +{ + quad.fill(0); + lin.fill(0); + for (int j=0; j < ideals.sz(); j++){ + Idealspacing const*i=ideals[j]; + int l = col_id(i->left); + int r = col_id(i->right); + + quad(r,r) += i->hooke; + quad(r,l) -= i->hooke; + quad(l,r) -= i->hooke; + quad(l,l) += i->hooke; + + lin(r) -= i->space*i->hooke; + lin(l) += i->space*i->hooke; + + c += sqr(i->space); + } +} + +// put the constraints into the LP problem +void +Spacing_problem::make_constraints(Mixed_qp& lp) const +{ + int dim=cols.sz(); + for (int j=0; j < dim; j++) { + Colinfo *c=&(cols[j]); + if (c->fixed) { + lp.add_fixed_var(j,c->fixpos); + } + if (j > 0){ + Vector c1(dim); + + + c1(j)=1.0 ; + c1(j-1)=-1.0 ; + lp.add_inequality_cons(c1, cols[j-1].minright() + + cols[j].minleft()); + } + } +} + +svec +Spacing_problem::solve() const +{ + print(); + OK(); + assert(check_feasible()); + + + /* optimalisatiefunctie */ + Mixed_qp lp(cols.sz()); + make_matrices(lp.quad,lp.lin, lp.const_term); + make_constraints(lp); + Vector start=find_initial_solution(); + Vector sol(lp.solve(start)); + if (!check_constraints(sol)) { + WARN << "solution doesn't satisfy constraints.\n" ; + } + + + svec posns(sol); + posns.add(lp.eval(sol)); + return posns; +} + +/* + add one column to the problem. +*/ +void +Spacing_problem::add_column(const PCol *col, bool fixed, Real fixpos) +{ + Colinfo c; + c.fixed=fixed; + c.fixpos=fixpos; + assert(col); + c.pcol_=col; + cols.add(c); +} + +void +Spacing_problem::add_ideal(const Idealspacing *i) +{ + const PCol *l =i->left; + const PCol *r= i->right; + + if (!contains(l) || !contains(r)) { + return; + } + ideals.add(i); +} + +void +Spacing_problem::print_ideal(const Idealspacing*id)const +{ +#ifndef NPRINT + int l = col_id(id->left); + int r = col_id(id->right); + + mtor << "between " << l <<","<paper_->lookup_->linestaff(l); +} + +Symbol +Linestaff::get_stafsym(Real width)const +{ + String w(print_dimen(width)); + return stafsym->eval(w); +} diff --git a/src/lookup.cc b/src/lookup.cc new file mode 100644 index 0000000000..d0ce3cb743 --- /dev/null +++ b/src/lookup.cc @@ -0,0 +1,160 @@ +#include "lookup.hh" +#include "debug.hh" +#include "symtable.hh" +#include "dimen.hh" +#include "tex.hh" + +void +Lookup::parse(Text_db&t) +{ + symtables_->read(t) ; +} + +Lookup::Lookup() +{ + symtables_ = new Symtables; +} + +Lookup::~Lookup() +{ + delete symtables_; +} + +Symbol +Lookup::ball(int j) +{ + if (j > 4) + j = 4; + + Symtable * st = (*symtables_)("balls"); + return st->lookup(String(j)); +} + +Symbol +Lookup::rest(int j) +{ + return (*symtables_)("rests")->lookup(String(j)); +} + + +Symbol +Lookup::bar(String s) +{ + return (*symtables_)("bars")->lookup(s); +} + Symbol +Lookup::dots(int j) +{ + if (j>3) + error("max 3 dots"); + return (*symtables_)("dots")->lookup(j); +} + +Symbol +Lookup::flag(int j) +{ + 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 a; + a.add(arg); + ret.tex = substitute_args(ret.tex, a); + + return ret; +} + +/****************************************************************/ +// bare bones. + +struct Linestaf_symbol : Parametric_symbol { + int lines; + Linestaf_symbol(int n, Symtables*s): Parametric_symbol(s) { lines = n;} + Symbol eval(svec)const; +}; + + +Symbol +Linestaf_symbol::eval(svec w)const +{ + Real wid = w[0].fvalue(); + + Symbol s; + s.dim.x = Interval(0,wid); + Real dy=(lines-1)*convert_dimen(5,"pt"); // TODO! + s.dim.y = Interval(0,dy); + svec a; + a.add(lines); + a.add(w[0]); + s.tex = (*symtables_)("param")->lookup("linestaf").tex; + s.tex = substitute_args(s.tex, a); + return s; +} + +/****************************************************************/ + + +struct Meter_sym:Parametric_symbol { + + Meter_sym(Symtables*s) : Parametric_symbol(s){ } + Symbol eval(svec a) const{ + Symbol s; + s.dim.x = Interval( convert_dimen(-5,"pt"), + convert_dimen(5,"pt")); + s.dim.y = Interval(0, convert_dimen(10,"pt") ); // todo + String src = (*symtables_)("param")->lookup("meter").tex; + s.tex = substitute_args(src,a); + return s; + } +}; +/****************************************************************/ + +struct Stem_sym:Parametric_symbol { + + Stem_sym(Symtables*s) : Parametric_symbol(s) { } + Symbol eval(svec a) const { + Real y1 = a[0].fvalue(); + Real y2 = a[1].fvalue(); + assert(y1 <= y2); + Symbol s; + s.dim.x = Interval(0,0); + s.dim.y = Interval(y1,y2); + + String src = (*symtables_)("param")->lookup("stem").tex; + s.tex = substitute_args(src,a); + return s; + } +}; + +Parametric_symbol * +Lookup::meter(String ) +{ + return new Meter_sym(symtables_); +} + +Parametric_symbol * +Lookup::linestaff(int n) +{ + return new Linestaf_symbol(n,symtables_); +} + +Parametric_symbol* +Lookup::stem() +{ + return new Stem_sym(symtables_); +} diff --git a/src/main.cc b/src/main.cc new file mode 100644 index 0000000000..c45de7a683 --- /dev/null +++ b/src/main.cc @@ -0,0 +1,79 @@ +#include +#include +#include "lgetopt.hh" +#include "misc.hh" +#include "string.hh" +#include "main.hh" + +extern void parse_file(String s); + +long_option_init theopts[] = { + 1, "output", 'o', + 0, "warranty", 'w', + 0, "help", 'h', + 0,0,0 +}; + +void +help() +{ + cout << + "--help, -h This help\n" + "--warranty, -w show warranty & copyright\n" + "--output, -o set default output\n"; +} +void notice() +{ + cout << + "LilyPond, a music typesetter.\n" + "Copyright (C) 1996 by\n" + " Han-Wen Nienhuys \n" + "\n" + " This program is free software; you can redistribute it and/or\n" + "modify it under the terms of the GNU General Public License version 2\n" + "as published by the Free Software Foundation.\n" + "\n" + " This program is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" + "General Public License for more details.\n" + "\n" + " You should have received a copy (refer to the file COPYING) of the\n" + "GNU General Public License along with this program; if not, write to\n" + "the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,\n" + "USA.\n"; +} + +int +main (int argc, char **argv) +{ + Getopt_long oparser(argc, argv,theopts); + debug_init(); + cout << get_version(); + + while (long_option_init * opt = oparser()) { + switch ( opt->shortname){ + case 'o': + set_default_output(oparser.optarg); + break; + case 'w': + notice(); + exit(0); + break; + case 'h': + help(); + exit(0); + break; + default: + assert(false); + break; + } + } + char *arg = oparser.get_next_arg(); + + if (!arg) arg = ""; + parse_file(arg); + + do_scores(); + exit (0); +} diff --git a/src/melodicstaff.cc b/src/melodicstaff.cc new file mode 100644 index 0000000000..17916d2f22 --- /dev/null +++ b/src/melodicstaff.cc @@ -0,0 +1,59 @@ +#include "melodicstaff.hh" +#include "stem.hh" +#include "rest.hh" +#include "notehead.hh" +#include "paper.hh" +#include "molecule.hh" +#include "linestaff.hh" +#include "rhythmstaff.hh" +#include "sccol.hh" + +const int NO_LINES=5; +const int BOTTOM_POSITION=2; // e is on bottom line of 5-staff... + +void +Melodic_staff::set_output(PScore*ps) +{ + theline = new Linestaff(NO_LINES,ps); + Simple_staff::set_output(ps); +} + + +Notehead* +Melodic_staff::get_notehead(Note_req *rq) +{ + int b = rq->rhythmic()->balltype; + int d = rq->rhythmic()->dots; + + Notehead *n =new Notehead((NO_LINES-1)*2); + n->balltype =b; + n->dots = d; + n->position = rq->note()->height() - BOTTOM_POSITION; + return n; +} + + +Stem * +Melodic_staff::get_stem(Stem_req*rq) +{ + Stem * s = new Stem(NO_LINES-1); + s->flag = rq->stem_number; + return s; +} + +/* + creation + */ +Staff * +get_new_melodicstaff() +{ + return new Melodic_staff; +} + + + +Melodic_staff* +Melodic_staff::clone()const +{ + return new Melodic_staff(*this); +} diff --git a/src/meter.cc b/src/meter.cc new file mode 100644 index 0000000000..0afa8ea1a1 --- /dev/null +++ b/src/meter.cc @@ -0,0 +1,20 @@ +#include "string.hh" +#include "molecule.hh" +#include "meter.hh" +#include "paper.hh" +#include "lookup.hh" + + +Meter::Meter(svec a) + :args(a) +{ +} +void +Meter::preprocess() +{ + Parametric_symbol *p = paper()->lookup_->meter("general"); + Symbol s = p->eval(args); + delete p; + output = new Molecule(Atom(s)); +} + diff --git a/src/misc.cc b/src/misc.cc new file mode 100644 index 0000000000..54746fd836 --- /dev/null +++ b/src/misc.cc @@ -0,0 +1,14 @@ +#include "misc.hh" +#include "glob.hh" + +#include + +int intlog2(int d) { + int i=0; + while (!(d&1)) { + d/= 2; i++; + } + assert(!(d/2)); + return i; +} + diff --git a/src/molecule.cc b/src/molecule.cc new file mode 100644 index 0000000000..e8c4d2adec --- /dev/null +++ b/src/molecule.cc @@ -0,0 +1,144 @@ +#include "glob.hh" +#include "dimen.hh" +#include "string.hh" +#include "molecule.hh" +#include "symbol.hh" +#include "debug.hh" +#include "tex.hh" + +void +Atom::print() const +{ + mtor << "texstring: " < a; + a.add(print_dimen(off.y)); + a.add(print_dimen(off.x)); + a.add(sym.tex); + return substitute_args(s, a); +} + + +String +Molecule::TeXstring() const +{ + String s; + for(PCursor c(ats); c.ok(); c++) + s+=c->TeXstring(); + return s; +} + +Box +Molecule::extent() const +{ + Box b; + for(PCursor c(ats); c.ok(); c++) + b.unite(c->extent()); + return b; +} + +void +Molecule::translate(Offset o) +{ + for (PCursor c(ats); c.ok(); c++) + c->translate(o); +} + +void +Molecule::add(const Molecule &m) +{ + for (PCursor c(m.ats); c.ok(); c++) { + add(**c); + } +} + +void +Molecule::add_right(const Molecule &m) +{ + if (!ats.size()) { + add(m); + return; + } + Real xof=extent().x.max - m.extent().x.min; + Molecule toadd(m); + toadd.translate(Offset(xof, 0.0)); + add(toadd); +} + +void +Molecule::add_left(const Molecule &m) +{ + if (!ats.size()) { + add(m); + return; + } + Real xof=extent().x.min - m.extent().x.max; + Molecule toadd(m); + toadd.translate(Offset(xof, 0.0)); + add(toadd); +} + + +void +Molecule::add_top(const Molecule &m) +{ + if (!ats.size()) { + add(m); + return; + } + Real yof=extent().y.max - m.extent().y.min; + Molecule toadd(m); + toadd.translate(Offset(0,yof)); + add(toadd); +} + +void +Molecule::add_bot(const Molecule &m) +{ + if (!ats.size()) { + add(m); + return; + } + Real yof=extent().y.min- m.extent().y.max; + Molecule toadd(m); + toadd.translate(Offset(0,yof)); + add(toadd); +} + +void +Molecule::operator = (const Molecule&) +{ + assert(false); +} + +Molecule::Molecule(const Molecule&s) +{ + add(s); +} + +void +Molecule::print() const +{ + for (PCursor c(ats); c.ok(); c++) + c->print(); +} diff --git a/src/note.cc b/src/note.cc new file mode 100644 index 0000000000..0041bb7238 --- /dev/null +++ b/src/note.cc @@ -0,0 +1,206 @@ +#include + +#include "string.hh" +#include "real.hh" +#include "debug.hh" +#include "request.hh" +#include "voice.hh" +#include "notename.hh" +#include "vray.hh" + +int default_duration = 4, default_dots=0, default_octave=0; + +void +parse_duration(const char *a, int &j, int &intdur, int &dots) +{ + String durstr; + while (isdigit(a[j])) + { + durstr += a[j++]; + } + + dots=default_dots; + + while (a[j] == '.') + { + j++; + dots++; + } + + intdur = (durstr.len()) ? + durstr.value():default_duration; + + mtor << "dur " << intdur << "dots " << dots<= 2) { + Stem_req * st = new Stem_req(dur); + v->add(st); + } + + int oct, pit, acc; + bool forceacc; + parse_pitch(pitch, i, oct, forceacc, pit, acc); + char nm = pit + 'c'; + if (nm > 'g') + nm += 'a' - 'h'; + rq->name =nm; + + rq->octave = oct; + rq->accidental = acc; + rq->forceacc = forceacc; + rq->balltype = dur; + rq->dots = dots; + + rq->print(); + + v->add(rq); + + return v; +} + +Voice_element * +get_rest_element(String, String durstr) +{ + Voice_element*v = new Voice_element; + int i=0; + + int dur, dots; + parse_duration(durstr, i, dur, dots); + i=0; + + Rest_req * rq = new Rest_req; + + rq->balltype = dur; + rq->dots = dots; + rq->print(); + v->add(rq); + + return v; +} + +void +set_default_duration(String d) +{ + int i=0; + parse_duration(d, i, default_duration, default_dots); +} + + +void +set_default_pitch(String d) +{ + int i=0; + bool b; + int l,s; + parse_pitch(d, i, default_octave, b, l,s); +} + +Request* +get_request(char c) +{ + Request* ret=0; + switch (c) { + case '[': + case ']': + ret = new Beam_req; + break; + + case ')': + case '(': + ret = new Slur_req; + break; + default: + assert(false); + break; + } + + switch (c) { + case '(': + case '[': + ret->span()->spantype = Span_req::START; + break; + case ')': + case ']': + ret->span()->spantype = Span_req::STOP; + break; + default: + assert(false); + break; + } + + return ret; +} + +void +add_requests(Voice_element *v, svec &req) +{ + for (int i = 0; i < req.sz(); i++) { + v->add(req[i]); + } + req.set_size(0); +} diff --git a/src/notehead.cc b/src/notehead.cc new file mode 100644 index 0000000000..a103e69b3d --- /dev/null +++ b/src/notehead.cc @@ -0,0 +1,65 @@ +#include "notehead.hh" +#include "dimen.hh" +#include "debug.hh" +#include "paper.hh" +#include "lookup.hh" +#include "molecule.hh" + + +Notehead::Notehead(int ss) +{ + staff_size=ss; + position = 0; + balltype = 0; + dots = 0; +} + +void +Notehead::print()const +{ + mtor << "Head "<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)); +} + diff --git a/src/notename.cc b/src/notename.cc new file mode 100644 index 0000000000..8ebc4df244 --- /dev/null +++ b/src/notename.cc @@ -0,0 +1,30 @@ +#include "glob.hh" +#include "string.hh" + + +/// change this along with lex file for other notenames. +const char *notetab[] = +{ +"ceses", "ces", "c", "cis", "cisis", +"deses", "des", "d", "dis", "disis", +"eses", "es", "e", "eis", "eisis", +"feses", "fes", "f", "fis", "fisis", +"geses", "ges", "g", "gis", "gisis", +"ases", "as", "a", "ais", "aisis", +"beses", "bes", "b", "bis", "bisis", +0 +}; + +void +lookup_notename(int &large, int &small, String s) +{ + int i; + for (i =0; notetab[i]; i++) + if (s == notetab[i]) + { + large = i /5; + small = i %5 - 2; + return; + } + assert(false); +} diff --git a/src/paper.cc b/src/paper.cc new file mode 100644 index 0000000000..8cd98339d4 --- /dev/null +++ b/src/paper.cc @@ -0,0 +1,82 @@ +#include + +#include "paper.hh" +#include "debug.hh" +#include "lookup.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)); +} +Real +Paperdef::rule_thickness()const +{ + return convert_dimen(0.4, "pt"); +} +Paperdef::Paperdef() +{ + lookup_ = new Lookup(); + parse(); + linewidth = convert_dimen(15,"cm"); // in cm for now + whole_width= 8*note_width(); + geometric_ = PHI; +} + +void +Paperdef::parse() +{ + Text_db symini("symbol.ini"); + + + while (!symini.eof()) { + + Text_record r( symini++); + + if (r[0] == "symboltables") + lookup_->parse(symini); + } +} + +Paperdef::~Paperdef() +{ + delete lookup_; +} + +Real +Paperdef::interline() const +{ + return lookup_->ball(4).dim.y.length(); +} +Real +Paperdef::note_width()const +{ + return lookup_->ball(4).dim.x.length( ); +} +Real +Paperdef::standard_height() const +{ + return convert_dimen(20,"pt"); +} + +void +Paperdef::print() const +{ +#ifndef NPRINT + mtor << "Paper {width: " << print_dimen(linewidth); + mtor << "whole: " << print_dimen(whole_width); + mtor << "out: " < + +#include "lexer.hh" +#include "paper.hh" +#include "staff.hh" +#include "score.hh" +#include "main.hh" +#include "keyword.hh" +#include "scommands.hh" +#include "debug.hh" +#include "parseconstruct.hh" +#include "dimen.hh" +#include "identifier.hh" + +#ifndef NDEBUG +#define YYDEBUG 1 +#endif + +svec pre_reqs, post_reqs; +%} + + +%union { + Real real; + Command *command; + Identifier *id; + Score_commands *scommands; + Voice *voice; + Voice_element *el; + Staff *staff; + String *string; + Score *score; + const char *consstr; + Paperdef *paper; + Request* request; + int i; + char c; +} + +%token VOICE STAFF SCORE TITLE RHYTHMSTAFF BAR NOTENAME OUTPUT +%token CM IN PT MM PAPER WIDTH METER UNITSPACE SKIP COMMANDS +%token MELODICSTAFF GEOMETRIC START_T DURATIONCOMMAND OCTAVECOMMAND + +%token IDENTIFIER +%token NEWIDENTIFIER +%token PITCH DURATION RESTNAME +%token REAL +%token STRING +%token OPEN_REQUEST_PARENS CLOSE_REQUEST_PARENS + + +%type unit + +%type declaration +%type paper_block paper_body +%type dim +%type voice_block voice_body voice_elts voice_elts_dollar +%type voice_elt +%type score_command +%type score_block score_body +%type staff_block rhythmstaff_block rhythmstaff_body +%type melodicstaff_block melodicstaff_body staffdecl +%type int +%type score_commands_block score_commands_body +%type post_request pre_request + + +%% + +mudela: /* empty */ + | mudela score_block { + add_score($2); + } + | mudela add_declaration { } + ; + +add_declaration: declaration { + add_identifier($1); + } + ; + +declaration: + NEWIDENTIFIER '=' staff_block { + $$ = new Staff_id(*$1, $3); + delete $1; // this sux + } + | NEWIDENTIFIER '=' voice_block { + $$ = new Voice_id(*$1, $3); + delete $1; + } + ; + + +score_block: SCORE '{' score_body '}' { $$ = $3; } + ; + +score_body: { $$ = new Score; } + | score_body staff_block { $$->add($2); } + | score_body score_commands_block { $$->set($2); } + | score_body paper_block { $$->set($2); } + ; +score_commands_block: + COMMANDS '{' score_commands_body '}' { $$ =$3;} + ; + +score_commands_body: { $$ = new Score_commands; } + | score_commands_body score_command { + $$->parser_add($2); + } + ; + +paper_block: + PAPER '{' paper_body '}' { $$ = $3; } + ; + +paper_body: + /* empty */ { $$ = new Paperdef; } + | paper_body WIDTH dim { $$->linewidth = $3;} + | paper_body OUTPUT STRING { $$->outfile = *$3; + delete $3; + } + | paper_body UNITSPACE dim { $$->whole_width = $3; } + | paper_body GEOMETRIC REAL { $$->geometric_ = $3; } + ; + +dim: + REAL unit { $$ = convert_dimen($1,$2); } + ; + + +unit: CM { $$ = "cm"; } + |IN { $$ = "in"; } + |MM { $$ = "mm"; } + |PT { $$ = "pt"; } + ; + +/* + staff +*/ +staff_block: + staffdecl + | rhythmstaff_block + | melodicstaff_block + ; + +staffdecl: STAFF '{' IDENTIFIER '}' { $$ = $3->staff()->clone(); } + ; + +rhythmstaff_block: + RHYTHMSTAFF '{' rhythmstaff_body '}' { $$ = $3; } + ; + +rhythmstaff_body: + /* empty */ { $$ = get_new_rhythmstaff(); } + | rhythmstaff_body voice_block { $$->add_voice($2); } + ; + +melodicstaff_block: + MELODICSTAFF '{' melodicstaff_body '}' { $$ = $3; } + ; + +melodicstaff_body: + /* empty */ { $$ = get_new_melodicstaff(); } + | melodicstaff_body voice_block { $$->add_voice($2); } + ; + +/* + voice +*/ +voice_block: + VOICE '{' voice_body '}' { $$ = $3; } + ; + + +voice_body: + IDENTIFIER { $$ = new Voice(*$1->voice()); } + | voice_elts_dollar { $$ = $1; } + | voice_body START_T REAL { $$->start = $3; } + ; + + + + +voice_elts_dollar: + '$' voice_elts '$' { $$ = $2; } + ; + +voice_elts: + /* empty */ { + $$ = new Voice; + } + | voice_elts pre_requests voice_elt post_requests { + add_requests($3, pre_reqs); + add_requests($3, post_reqs); + $$->add($3); + } + + | voice_elts voice_command { } + ; + +post_requests: + { + assert(post_reqs.empty()); + } + | post_requests post_request { + post_reqs.add($2); + } + ; + +post_request: + CLOSE_REQUEST_PARENS { $$ = get_request($1); } + ; + +pre_requests: + | pre_requests pre_request { + pre_reqs.add($2); + } + ; + +pre_request: + OPEN_REQUEST_PARENS { $$ = get_request($1); } + ; +/* +*/ +voice_command: + DURATIONCOMMAND DURATION { + set_default_duration(*$2); + delete $2; + } + | OCTAVECOMMAND PITCH { + set_default_pitch(*$2); + delete $2; + } + ; + +voice_elt: + PITCH DURATION { + $$ = get_note_element(*$1, *$2); + delete $1; + delete $2; + } + | RESTNAME DURATION { + $$ = get_rest_element(*$1, *$2); + delete $1; + delete $2; + } + | PITCH { $$ = get_note_element(*$1, ""); + delete $1; + } + | RESTNAME { $$ = get_rest_element(*$1, ""); + delete $1; + } + ; + +score_command: + SKIP int ':' REAL { + $$ = get_skip_command($2, $4); + } + | METER int int { + $$ = get_meterchange_command($2, $3); + } +/* | PARTIALMEASURE REAL { + $$ = get_partial_command($2); + }*/ + ; + + +int: + REAL { + $$ = int($1); + if (ABS($1-Real(int($$))) > 1e-8) + yyerror("expecting integer number"); + + } + ; + +%% + +void +parse_file(String s) +{ + *mlog << "Parsing ... "; +#ifdef YYDEBUG + yydebug = !monitor.silence("Parser"); +#endif + new_input(s); + yyparse(); + delete_identifiers(); + kill_lexer(); + *mlog << "\n"; +} diff --git a/src/pcol.cc b/src/pcol.cc new file mode 100644 index 0000000000..902f57bab2 --- /dev/null +++ b/src/pcol.cc @@ -0,0 +1,118 @@ +#include "pcol.hh" +#include "pstaff.hh" +#include "debug.hh" + +void +Idealspacing::print() const +{ +#ifndef NPRINT + mtor << "idealspacing {" ; + mtor << "distance "<= 0 && left && right); +#endif +} + +/****************************************************************/ + +Interval +PCol::width() const +{ + Interval w; + + for (PCursor ic(its); ic.ok(); ic++) + w.unite(ic->width()); + if (w.empty()) + w.unite(Interval(0,0)); + return w; +} + +void +PCol::print() const +{ + #ifndef NPRINT + mtor << "PCol {"; + mtor << "# symbols: " << its.size() ; + if (breakable()){ + mtor << "pre,post: "; + prebreak->print(); + postbreak->print(); + } + mtor << "extent: " << width().min << ", " << width().max << "\n"; + mtor << "}\n"; + #endif +} + +int +PCol::compare(const PCol &, const PCol &) +{ + assert(false); + return 0 ; +} + +void +PCol::OK () const +{ + if (prebreak || postbreak ) { + assert(prebreak&&postbreak); + assert(prebreak->daddy == this); + assert(postbreak->daddy == this); + } + +} + +void +PCol::set_breakable() +{ + if (breakable()) + return; + + prebreak = new PCol(this); + postbreak = new PCol(this); + used = true; +} + +bool +PCol::breakable() const +{ + return prebreak||postbreak; +} + +PCol::PCol(PCol *parent) { + daddy = parent; + prebreak=0; + postbreak=0; + line=0; + used = false; +} + +PCol::~PCol() +{ + + delete prebreak; + + delete postbreak; +} + +void +PCol::add( Item *i) +{ + its.bottom().add(i); + i->pcol_ = this; + used = true; +} + diff --git a/src/pscore.cc b/src/pscore.cc new file mode 100644 index 0000000000..8d7067760f --- /dev/null +++ b/src/pscore.cc @@ -0,0 +1,205 @@ +// utility functions for PScore +#include "debug.hh" +#include "spanner.hh" +#include "paper.hh" +#include "molecule.hh" +#include "dimen.hh" +#include "scoreline.hh" +#include "pscore.hh" +#include "tstream.hh" + + +void +PScore::clean_cols() +{ + for (PCursor c(cols); c.ok(); ) + if (!c->used) { + c.del(); + } else + c++; +} + + +void +PScore::add(PStaff *s) +{ + assert(s->pscore_ == this); + staffs.bottom().add(s); +} + +void +PScore::typeset_item(Item *i, PCol *c, PStaff *s, int breakstat) +{ + assert(c && i && s); +// assert(!breakstat != 4 || c->breakable() ); + if (breakstat == 0) { + typeset_item(i, c->prebreak, s); + return; + } + + if (breakstat == 2) { + typeset_item(i, c->postbreak, s); + return; + } + + + its.bottom().add(i); + s->add(i); + c->add(i); + + /* first do this, because i->width() may follow the 0-pointer */ + i->preprocess(); + + + if (c->daddy && c == c->daddy->prebreak) { // makeshift. + + Interval iv (i->width()); + if (!iv.empty()) { + svec col_its (select_items(s, c)); + for (int j =0; j < col_its.sz(); j++) + col_its[j]->translate(Offset(-iv.length(),0)); + i->translate (Offset(-iv.max, 0)); + } + } + +} + +void +PScore::typeset_spanner(Spanner*sp, PStaff*ps) +{ + sp->preprocess(); + sp->pstaff_ = ps; + spanners.bottom().add(sp); + ps->spans.bottom().add(sp); + sp->left->starters.bottom().add(sp); + sp->right->stoppers.bottom().add(sp); +} + + +void +PScore::add_line(svec curline, svec config) +{ + Line_of_score *p = new Line_of_score(curline,this); + lines.bottom().add(p); + for (int i=0; i < curline.sz(); i++){ + PCol *c=(PCol *)curline[i]; // so, this isn't really const. + c->hpos= config[i]; + } +} + +Idealspacing* +PScore::get_spacing(PCol*l, PCol*r) +{ + assert(l!=r); + for (PCursor ic (suz); ic.ok(); ic++) { + if (ic->left == l && ic->right == r){ + return ic; + } + } + + Idealspacing*ip =new Idealspacing(l,r); + suz.bottom().add(ip); + + return ip; +} + + +/* + return all breakable columns + */ +svec +PScore::find_breaks() const +{ + svec retval; + for (PCursor c(cols); c.ok(); c++) + if (c->breakable()) + retval.add(c); + + return retval; +} + +void +PScore::add(PCol *p) +{ + cols.bottom().add(p); +} + +PScore::PScore( Paperdef*p) +{ + paper_ = p; +} + +void +PScore::output(Tex_stream &ts) +{ + int l=1; + + for (PCursor lic(lines); lic.ok(); lic++) { + ts << "% line of score no. " << l++ <<"\n"; + ts << lic->TeXstring(); + if ((lic+1).ok()) + ts << "\\interscoreline\n"; + } +} + + +svec +PScore::select_items(PStaff*ps , PCol*pc) +{ + svec ret; + assert(ps && pc); + for (PCursor ic(pc->its); ic.ok(); ic++){ + if (ic->pstaff_ == ps) + ret.add((Item*)(const Item*)ic); + } + return ret; +} + +void +PScore::OK()const +{ +#ifdef NDEBUG + for (PCursor cc(cols); cc.ok(); cc++) + cc->OK(); + for (PCursor ic(suz); ic.ok(); ic++) + ic->OK(); +#endif +} + +void +PScore::print() const +{ +#ifndef NPRINT + mtor << "PScore { "; + paper_->print(); + mtor << "\ncolumns: "; + for (PCursor cc(cols); cc.ok(); cc++) + cc->print(); + + mtor << "\nideals: "; + for (PCursor ic(suz); ic.ok(); ic++) + ic->print(); + mtor << "}\n"; +#endif +} + +void +PScore::preprocess() +{ +#if 0 + for (PCursor ic(its); ic.ok(); ic++){ + ic->preprocess(); + } +#endif +} + +void +PScore::postprocess() +{ + for (PCursor ic(spanners); ic.ok(); ic++) { + ic->process(); + } + for (PCursor ic(its); ic.ok(); ic++){ + ic->postprocess(); + } +} diff --git a/src/pstaff.cc b/src/pstaff.cc new file mode 100644 index 0000000000..255fceeadd --- /dev/null +++ b/src/pstaff.cc @@ -0,0 +1,14 @@ +#include "pstaff.hh" + +PStaff::PStaff(PScore*ps) +{ + pscore_=ps; + stafsym = 0; +} + +void +PStaff::add(Item *i ) +{ + its.bottom().add(i); + i->pstaff_ = this; +} diff --git a/src/qlp.cc b/src/qlp.cc new file mode 100644 index 0000000000..3dd8e4227e --- /dev/null +++ b/src/qlp.cc @@ -0,0 +1,147 @@ +#include "debug.hh" +#include "const.hh" +#include "qlp.hh" +#include "choleski.hh" + +void +Mixed_qp::add_equality_cons(Vector , double ) +{ + assert(false); +} + +void +Mixed_qp::add_fixed_var(int i, Real r) +{ + eq_cons.add(i); + eq_consrhs.add(r); +} + +void +Ineq_constrained_qp::add_inequality_cons(Vector c, double r) +{ + cons.add(c); + consrhs.add(r); +} + +Ineq_constrained_qp::Ineq_constrained_qp(int novars): + quad(novars), + lin(novars) +{ +} + +void +Ineq_constrained_qp::OK() const +{ +#ifndef NDEBUG + assert(cons.sz() == consrhs.sz()); + Matrix Qdif= quad - quad.transposed(); + assert(Qdif.norm()/quad.norm() < EPS); +#endif +} + + +Real +Ineq_constrained_qp::eval (Vector v) +{ + return v * quad * v + lin * v + const_term; +} +/* + eliminate appropriate variables, until we have a Ineq_constrained_qp + then solve that. + + PRE + cons should be ascending + */ +Vector +Mixed_qp::solve(Vector start) const +{ + print(); + Ineq_constrained_qp pure(*this); + + for (int i= eq_cons.sz()-1; i>=0; i--) { + pure.eliminate_var(eq_cons[i], eq_consrhs[i]); + start.del(eq_cons[i]); + } + Vector sol = pure.solve(start); + for (int i= 0; i < eq_cons.sz(); i++) { + sol.insert( eq_consrhs[i],eq_cons[i]); + } + return sol; +} + +/* + assume x(idx) == value, and adjust constraints, lin and quad accordingly + */ +void +Ineq_constrained_qp::eliminate_var(int idx, Real value) +{ + Vector row(quad.row(idx)); + row*= value; + + quad.delete_row(idx); + + quad.delete_column(idx); + + lin.del(idx); + row.del(idx); + lin +=row ; + + for (int i=0; i < cons.sz(); i++) { + consrhs[i] -= cons[i](idx) *value; + cons[i].del(idx); + } +} + + + + +Mixed_qp::Mixed_qp(int n) + : Ineq_constrained_qp(n) +{ +} + +void +Mixed_qp::OK() const +{ +#ifndef NDEBUG + Ineq_constrained_qp::OK(); + assert(eq_consrhs.sz() == eq_cons.sz()); +#endif +} +void +Ineq_constrained_qp::print() const +{ +#ifndef NPRINT + mtor << "Quad " << quad; + mtor << "lin " << lin <<"\n"; + for (int i=0; i < cons.sz(); i++) { + mtor << "constraint["<= " << consrhs[i]; + mtor << "\n"; + } +#endif +} +void +Mixed_qp::print() const +{ +#ifndef NPRINT + Ineq_constrained_qp::print(); + for (int i=0; i < eq_cons.sz(); i++) { + mtor << "eq cons "< binding; + for (int i=0; i < cons.sz(); i++) { + Real R=cons[i] * sol- consrhs[i]; + assert(R> -EPS); + if (R < EPS) + binding.add(i); + } + // KKT check... + // todo +} diff --git a/src/qlpsolve.cc b/src/qlpsolve.cc new file mode 100644 index 0000000000..13bd30e89b --- /dev/null +++ b/src/qlpsolve.cc @@ -0,0 +1,255 @@ +#include "qlpsolve.hh" +#include "const.hh" +#include "debug.hh" +#include "choleski.hh" + +const Real TOL=1e-2; // roughly 1/10 mm + +String +Active_constraints::status() const +{ + String s("Active|Inactive ["); + for (int i=0; i< active.sz(); i++) { + s += String(active[i]) + " "; + } + + s+="| "; + for (int i=0; i< inactive.sz(); i++) { + s += String(inactive[i]) + " "; + } + s+="]"; + + return s; +} + +void +Active_constraints::OK() { + H.OK(); + A.OK(); + assert(active.sz() +inactive.sz() == opt->cons.sz()); + assert(H.dim() == opt->dim()); + assert(active.sz() == A.rows()); + svec allcons; + + for (int i=0; i < opt->cons.sz(); i++) + allcons.add(0); + for (int i=0; i < active.sz(); i++) { + int j = active[i]; + allcons[j]++; + } + for (int i=0; i < inactive.sz(); i++) { + int j = inactive[i]; + allcons[j]++; + } + for (int i=0; i < allcons.sz(); i++) + assert(allcons[i] == 1); +} + +Vector +Active_constraints::get_lagrange(Vector gradient) +{ + Vector l(A*gradient); + + return l; +} + +void +Active_constraints::add(int k) +{ + // add indices + int cidx=inactive[k]; + active.add(cidx); + + inactive.swap(k,inactive.sz()-1); + inactive.pop(); + + Vector a( opt->cons[cidx] ); + // update of matrices + Vector Ha = H*a; + Real aHa = a*Ha; + if (ABS(aHa) > EPS) { + /* + a != 0, so if Ha = O(EPS), then + Ha * aH / aHa = O(EPS^2/EPS) + + if H*a == 0, the constraints are dependent. + */ + H -= Matrix(Ha , Ha)/(aHa); + + + /* + sorry, don't know how to justify this. .. + */ + Vector addrow(Ha/(aHa)); + A -= Matrix(A*a, addrow); + A.insert_row(addrow,A.rows()); + }else + WARN << "degenerate constraints"; +} + +void +Active_constraints::drop(int k) +{ + int q=active.sz()-1; + + // drop indices + inactive.add(active[k]); + active.swap(k,q); + A.swap_rows(k,q); + active.pop(); + + Vector a(A.row(q)); + if (a.norm() > EPS) { + /* + + */ + H += Matrix(a,a)/(a*opt->quad*a); + A -= A*opt->quad*Matrix(a,a)/(a*opt->quad*a); + }else + WARN << "degenerate constraints"; + Vector rem_row(A.row(q)); + assert(rem_row.norm() < EPS); + A.delete_row(q); +} + + +Active_constraints::Active_constraints(Ineq_constrained_qp const *op) + : A(0,op->dim()), + H(op->dim()), + opt(op) +{ + for (int i=0; i < op->cons.sz(); i++) + inactive.add(i); + Choleski_decomposition chol(op->quad); + H=chol.inverse(); +} + +/* Find the optimum which is in the planes generated by the active + constraints. + */ +Vector +Active_constraints::find_active_optimum(Vector g) +{ + return H*g; +} + +/****************************************************************/ + +int +min_elt_index(Vector v) +{ + Real m=INFTY; int idx=-1; + for (int i = 0; i < v.dim(); i++){ + if (v(i) < m) { + idx = i; + m = v(i); + } + assert(v(i) <= INFTY); + } + return idx; +} + +///the numerical solving +Vector +Ineq_constrained_qp::solve(Vector start) const +{ + Active_constraints act(this); + + + act.OK(); + + + Vector x(start); + Vector gradient=quad*x+lin; + + + Vector last_gradient(gradient); + int iterations=0; + + while (iterations++ < MAXITER) { + Vector direction= - act.find_active_optimum(gradient); + + mtor << "gradient "<< gradient<< "\ndirection " << direction<<"\n"; + + if (direction.norm() > EPS) { + mtor << act.status() << '\n'; + + Real minalf = INFTY; + + Inactive_iter minidx(act); + + + /* + we know the optimum on this "hyperplane". Check if we + bump into the edges of the simplex + */ + + for (Inactive_iter ia(act); ia.ok(); ia++) { + + if (ia.vec() * direction >= 0) + continue; + Real alfa= - (ia.vec()*x - ia.rhs())/ + (ia.vec()*direction); + + if (minalf > alfa) { + minidx = ia; + minalf = alfa; + } + } + Real unbounded_alfa = 1.0; + Real optimal_step = MIN(minalf, unbounded_alfa); + + Vector deltax=direction * optimal_step; + x += deltax; + gradient += optimal_step * (quad * deltax); + + mtor << "step = " << optimal_step<< " (|dx| = " << + deltax.norm() << ")\n"; + + if (minalf < unbounded_alfa) { + /* bumped into an edge. try again, in smaller space. */ + act.add(minidx.idx()); + mtor << "adding cons "<< minidx.idx()<<'\n'; + continue; + } + /*ASSERT: we are at optimal solution for this "plane"*/ + + + } + + Vector lagrange_mult=act.get_lagrange(gradient); + int m= min_elt_index(lagrange_mult); + + if (m>=0 && lagrange_mult(m) > 0) { + break; // optimal sol. + } else if (m<0) { + assert(gradient.norm() < EPS) ; + + break; + } + + mtor << "dropping cons " << m<<'\n'; + act.drop(m); + } + if (iterations >= MAXITER) + WARN<<"didn't converge!\n"; + + mtor << ": found " << x<<" in " << iterations <<" iterations\n"; + assert_solution(x); + return x; +} + +/** Mordecai Avriel, Nonlinear Programming: analysis and methods (1976) + Prentice Hall. + + Section 13.3 + + This is a "projected gradient" algorithm. Starting from a point x + the next point is found in a direction determined by projecting + the gradient onto the active constraints. (well, not really the + gradient. The optimal solution obeying the active constraints is + tried. This is why H = Q^-1 in initialisation) ) + + + */ + diff --git a/src/request.cc b/src/request.cc new file mode 100644 index 0000000000..9928f62bed --- /dev/null +++ b/src/request.cc @@ -0,0 +1,101 @@ +#include "request.hh" +#include "debug.hh" + +#define VIRTUALCONS(T,R) R *T::clone() const { return new T(*this); } struct T +#define RCONS(T) VIRTUALCONS(T, Request) + +RCONS(Rest_req); +RCONS(Rhythmic_req); +RCONS(Stem_req); +RCONS(Note_req); +RCONS(Span_req); +RCONS(Slur_req); +RCONS(Beam_req); + +void +Request::print() const +{ +#ifndef NPRINT + mtor << "Req{ unknown }\n"; +#endif +} + +Request::Request() +{ + elt = 0; +} + +Note_req::Note_req() +{ + name = 'c'; + octave = 0; + accidental = 0; + forceacc = false; +} + +int +Note_req::height() const +{ + int s = name -'c'; + if (s < 0) + s+=7; + return s + octave*7; +} + +Rhythmic_req::Rhythmic_req() +{ + balltype = 1; + dots = 0; +} + +void +Rhythmic_req::print() const +{ + mtor << "rhythmic: " << balltype ; + int d =dots; + while (d--) + mtor << '.'; + mtor<<"\n"; +} + +void +Note_req::print() const +{ + mtor << "note: " << name << " oct: "<< octave; + Rhythmic_req::print(); +} + +void +Rest_req::print() const +{ + mtor << "rest, " ; + Rhythmic_req::print(); +} + +Real +wholes(int dur, int dots) +{ + Real f = 1.0/Real(dur); + Real delta = f; + + while (dots--) { + delta /= 2.0; + f += delta; + } + return f; +} + +Real +Rhythmic_req::duration() const { + return wholes( balltype,dots); +} + +Beam_req::Beam_req() +{ + nplet = 0; +} + +Span_req::Span_req() +{ + spantype = NOSPAN; +} diff --git a/src/rest.cc b/src/rest.cc new file mode 100644 index 0000000000..e448df37bd --- /dev/null +++ b/src/rest.cc @@ -0,0 +1,47 @@ +#include "rest.hh" +#include "dimen.hh" +#include "debug.hh" +#include "paper.hh" +#include "lookup.hh" +#include "molecule.hh" + + +Rest::Rest(int t, int d) +{ + balltype = t; + dots = d; +} + +void +Rest::print()const +{ + mtor << "Rest "<lookup_->rest(balltype); + + Molecule *m = new Molecule(Atom(s)); + if (dots) { + Symbol d =p->lookup_->dots(dots); + Molecule dm; + dm.add(Atom(d)); + m->add_right(dm); + } + output = m; +} + diff --git a/src/rhythmstaff.cc b/src/rhythmstaff.cc new file mode 100644 index 0000000000..e584254bfd --- /dev/null +++ b/src/rhythmstaff.cc @@ -0,0 +1,62 @@ +#include "molecule.hh" +#include "notehead.hh" +#include "stem.hh" +#include "linestaff.hh" +#include "rhythmstaff.hh" +#include "paper.hh" +#include "sccol.hh" +#include "rest.hh" + +void +Rhythmic_staff::set_output(PScore*ps) +{ + theline = new Linestaff(1,ps); + Simple_staff::set_output(ps); +} + +Item * +Rhythmic_staff::get_TYPESET_item(Command *com) +{ + Item *i = Simple_staff::get_TYPESET_item(com); + i->translate(Offset(0, + -score_->paper_->standard_height()/2)); + return i; +} + +Notehead* +Rhythmic_staff::get_notehead(Note_req *rq) +{ + int b = rq->rhythmic()->balltype; + int d = rq->rhythmic()->dots; + + Notehead *n =new Notehead(1); + n->balltype = b; + n->dots =d; + n->position = 0; + return n; +} + +Stem * +Rhythmic_staff::get_stem(Stem_req*rq) +{ + Stem * s = new Stem(0); + s->flag = rq->stem_number; + return s; +} + +/* + creation + */ +Staff * +get_new_rhythmstaff() +{ + return new Rhythmic_staff; +} + + + +Rhythmic_staff* +Rhythmic_staff::clone() const +{ + return new Rhythmic_staff(*this); +} diff --git a/src/sccol.cc b/src/sccol.cc new file mode 100644 index 0000000000..1dfc8f2176 --- /dev/null +++ b/src/sccol.cc @@ -0,0 +1,28 @@ +#include "sccol.hh" +#include "debug.hh" + +Score_column::Score_column(Real w) +{ + when = w; + pcol = new PCol(0); + musical = false; +} + +bool +Score_column::used() { + return pcol->used; +} + +void +Score_column::print() const +{ +#ifndef NPRINT + mtor << "Score_column { mus "<< musical <<" at " << when<<'\n'; + mtor << "durations: ["; + for (int i=0; i < durations.sz(); i++) + mtor << durations[i] << " "; + mtor << "]\n"; + pcol->print(); + mtor << "}\n"; +#endif +} diff --git a/src/scommands.cc b/src/scommands.cc new file mode 100644 index 0000000000..7b8c8ed9c5 --- /dev/null +++ b/src/scommands.cc @@ -0,0 +1,266 @@ +#include "scommands.hh" +#include "debug.hh" +#include "parseconstruct.hh" + +/* + maybe it's time for a "narrowing" cursor? + */ +PCursor +Score_commands::first(Real w) +{ + PCursor pc(*this); + while (pc.ok() && pc->when < w) + pc++; + + return pc; +} + +PCursor +Score_commands::last_insertion(Real w) +{ + PCursor pc(*this); + while (pc.ok() && pc->when <= w) + pc++; + return pc; +} + +void +Score_commands::add_seq(svec com) +{ + if (!com.sz()) + return; + Real when = com[0].when; + + PCursor pc(last_insertion(when)); + for (int i = 0; i < com.sz(); i++) { + Command *c = new Command(com[i]); + assert(com[i].when == when); + if (!pc.ok()) + pc.add(c); + else + pc.insert(c); + } +} + +void +Score_commands::set_breakable(Real when) +{ + bool found_typeset(false); + PCursor cc = first(when); + for (; cc.ok() && cc->when == when; cc++) { + if (cc->isbreak()) + return; + if (cc->code == TYPESET) + found_typeset=true; + } + + assert(!found_typeset); + + svec seq; + Command k(when); + k.code = BREAK_PRE; + seq.add(k); + k.code = BREAK_MIDDLE; + seq.add(k); + k.code = BREAK_POST; + seq.add(k); + k.code = BREAK_END; + seq.add(k); + + add_seq(seq); +} + +bool +Score_commands::is_breakable(Real w) +{ + PCursor cc = first(w); + for (; cc.ok() && cc->when == w; cc++) { + if (cc->isbreak()) + return true; + } + return false; +} + +void +Score_commands::insert_between(Command victim, PCursor firstc, + PCursor last) +{ + assert(last->when==firstc->when); + PCursor c(firstc+1); + while (c != last) { // hmm what if !last.ok()? + if (victim.priority > c->priority) { + c.insert(new Command(victim)); + return; + } + c++; + } + last.insert(new Command(victim)); +} + +void +Score_commands::add_command_to_break(Command pre, Command mid, Command post) +{ + Real w = pre.when; + PCursor c ( first(w)), f(c), l(c); + + while (!c->isbreak()) + c++; + f = c++; + while (!c->isbreak()) + c++; + l = c++; + + insert_between(pre, f, l); + f = l; + while (!c->isbreak()) + c++; + l = c++; + insert_between(mid, f, l); + f = l; + while (!c->isbreak()) + c++; + l = c++; + insert_between(post, f, l); + assert(l.ok() && l->when ==w && l->code == BREAK_END); +} + +void +Score_commands::parser_add(Command *c) +{ + bottom().add(c); +} + +void +Score_commands::process_add(Command c) +{ + bool encapsulate =false; + Real w = c.when; + Command pre(w); + Command mid(w); + Command post(w); + + + if (c.code == TYPESET) { + if (c.args[0] == "BAR") { + set_breakable(w); + encapsulate = true; + mid = c; + pre = c; + } + if (c.args[0] == "METER" && is_breakable(w)) { + encapsulate = true; + mid = c; + pre = c; + post =c; + } + } + + if (encapsulate) + add_command_to_break(pre, mid, post); + else { + svec seq; + seq.add(c); + add_seq(seq); + } +} + +/* + first and last column should be breakable. + Remove any command past the last musical column. + */ +void +Score_commands::clean(Real l) +{ + assert(l>0); + if (!is_breakable(0.0)) { + Command c(0.0); + c.code = TYPESET; + c.args.add("BAR"); + c.args.add("empty"); + process_add(c); + } + + PCursor bot(bottom()); + + while (bot.ok() && bot->when > l) { + mtor <<"removing "; + bot->print(); + bot.del(); + bot = bottom(); + } + + if (!is_breakable(l)) { + Command c(l); + c.code = TYPESET; + c.args.add("BAR"); + c.args.add("||"); + process_add(c); + } + OK(); +} + +void +Score_commands::OK() const +{ + for (PCursor cc(*this); cc.ok() && (cc+1).ok(); cc++) { + assert(cc->when <= (cc+1)->when); + if (cc->when == (cc+1)->when && !cc->isbreak() && !(cc+1)->isbreak()) + assert(cc->priority >= (cc+1)->priority); + } +} + +void +Score_commands::print() const +{ + for (PCursor cc(*this); cc.ok() ; cc++) { + cc->print(); + } +} + +/* + TODO + */ +Score_commands* +Score_commands::parse(Real l) const +{ + Score_commands*nc = new Score_commands; + int beats_per_meas=4; + Real measlen = 1.0; // 4/4 by default + + Real inbar=0.0; + int barcount=0; + Real wholes=0.0; + Real stoppos=0.0; + + { + Command c(0.0); + c.code = TYPESET; + c.args.add("BAR"); + c.args.add("empty"); + nc->process_add(c); + } + for (PCursor cc(*this); cc.ok() && cc->when <= l; cc++) { + assert (cc->code==INTERPRET); + if (cc->args[0] == "METER") { + beats_per_meas = cc->args[1].value(); + int one_beat = cc->args[2].value(); + measlen = beats_per_meas/Real(one_beat); + nc->process_add(*get_meter_command(wholes, beats_per_meas, one_beat)); + } + if (cc->args[0] == "SKIP") { + stoppos = wholes + cc->args[1].value() * measlen + + cc->args[2].fvalue(); + wholes += (measlen-inbar); // skip at least 1 measure + barcount++; + while (wholes <= stoppos) { + nc->process_add(*get_bar_command(wholes)); // liek + wholes += measlen; + barcount ++; + } + wholes = stoppos; + //something + } + } + + return nc; +} diff --git a/src/score.cc b/src/score.cc new file mode 100644 index 0000000000..1df13365f2 --- /dev/null +++ b/src/score.cc @@ -0,0 +1,224 @@ +#include "scommands.hh" +#include "tstream.hh" +#include "score.hh" +#include "sccol.hh" +#include "pscore.hh" +#include "staff.hh" +#include "debug.hh" +#include "paper.hh" + +void +Score::set(Paperdef*p) +{ + delete paper_; + paper_ = p; +} + +void +Score::output(String s) +{ + OK(); + if (paper_->outfile=="") + paper_->outfile = s; + + *mlog << "output to " << paper_->outfile << "...\n"; + Tex_stream the_output(paper_->outfile); + pscore_->output(the_output); +} + + +void +Score::process() +{ + *mlog << "Processing ... "; + set(commands_->parse(last())); + commands_->print(); + + if (!paper_) + paper_ = new Paperdef; + + commands_->clean(last()); + + /// distribute commands to disciples + distribute_commands(); + + pscore_ = new PScore(paper_); + for (PCursor sc(staffs_); sc.ok(); sc++) { + sc->set_output(pscore_); + sc->process(); + } + + // do this after processing, staffs first have to generate PCols. + do_pcols(); + calc_idealspacing(); + clean_cols(); + OK(); + // print(); + + pscore_->preprocess(); + *mlog << "Calculating ... "; + pscore_->calc_breaking(); + pscore_->postprocess(); + + // TODO: calculate vertical structs + // TODO: calculate mixed structs. + *mlog << "\n"; +} + +// remove empty cols with no spacing attached. +/* should rethink ownership of cols + */ +void +Score::clean_cols() +{ + for (PCursor sc(staffs_); sc.ok(); sc++) + sc->clean_cols(); + + for (PCursor c(cols_); c.ok(); ) { + if (!c->pcol->used) { + mtor << "removing : "; + c->print(); + c.del(); + } else + c++; + } + + pscore_->clean_cols(); +} +/* this sux. We should have Score_column create the appropriate PCol. + Unfortunately, PCols don't know about their position. + */ +// todo +PCursor +Score::create_cols(Real w) +{ + Score_column* c1 = new Score_column(w); + Score_column* c2 = new Score_column(w); + + c1->musical = false; + c2->musical = true; + + PCursor scc(cols_); + + for (; scc.ok(); scc++) { + assert(scc->when != w); + if (scc->when > w) + break; + } + + if (!scc.ok()) { + cols_.bottom().add(c1); + cols_.bottom().add(c2); + scc = cols_.bottom(); + scc --; + } else { + scc.insert(c1); + scc.insert(c2); + scc -= 2; + } + return scc; +} + +Score_column* +Score::find_col(Real w,bool mus) +{ + PCursor scc(cols_); + for (; scc.ok(); scc++) { + if (scc->when == w && scc->musical == mus) + return scc; + if (scc->when > w) + break; + } + scc = create_cols(w); + if (mus) + scc++; + return scc; +} + +void +Score::distribute_commands(void) +{ + for (PCursor sc(staffs_); sc.ok(); sc++) { + sc->add_commands(*commands_); + } +} +void +Score::add(Staff*s) +{ + s->score_ = this; + staffs_.bottom().add(s); +} + + +void +Score::do_pcols() +{ + PCursor sc(cols_); + for (; sc.ok(); sc++) { + pscore_->add(sc->pcol); + } +} +Real +Score::last() const +{ + Real l = 0; + for (PCursor stc(staffs_); stc.ok(); stc++) { + l = MAX(l, stc->last()); + } + return l; +} + +void +Score::OK() const +{ +#ifndef NDEBUG + for (PCursor sc(staffs_); sc.ok(); sc++) { + sc->OK(); + assert(sc->score_ == this); + } + staffs_.OK(); + cols_.OK(); + for (PCursor cc(cols_); cc.ok() && (cc+1).ok(); cc++) { + assert(cc->when <= (cc+1)->when); + } + commands_->OK(); +#endif +} + + +void +Score::print() const +{ +#ifndef NPRINT + mtor << "score {\n"; + for (PCursor sc(staffs_); sc.ok(); sc++) { + sc->print(); + } + for (PCursor sc(cols_); sc.ok(); sc++) { + sc->print(); + } + commands_->print(); + mtor << "}\n"; +#endif +} + +Score::Score() +{ + pscore_=0; + paper_ = 0; + commands_ = new Score_commands; +} + +Score::~Score() +{ + delete pscore_; + delete commands_; + delete paper_; +} + +void +Score::set(Score_commands*c) +{ + delete commands_; + commands_ = c; +} diff --git a/src/scoreline.cc b/src/scoreline.cc new file mode 100644 index 0000000000..7e40c6a76a --- /dev/null +++ b/src/scoreline.cc @@ -0,0 +1,43 @@ +#include "scoreline.hh" +#include "staffline.hh" +#include "dimen.hh" +#include "spanner.hh" +#include "symbol.hh" +#include "paper.hh" +#include "pcol.hh" +#include "pscore.hh" + + +String +Line_of_score::TeXstring() const +{ + String s("\\vbox{%<- line of score\n"); + for (PCursor sc(staffs); sc.ok(); sc++){ + s += sc->TeXstring(); + if ((sc+1).ok()) + s+= "\\interstaffline\n"; + } + s += "}"; + return s; +} + + +Line_of_score::Line_of_score(svec sv, + const PScore *ps) +{ + score = ps; + for (int i=0; i< sv.sz(); i++) { + PCol *p=(PCol *) sv[i]; + cols.bottom().add(p); + p->line=this; + } + + for (PCursor sc(score->staffs); sc.ok(); sc++) + staffs.bottom().add(new Line_of_staff(this, sc)); +} +/* construct a line with the named columns. Make the line field + in each column point to this + + #sv# isn't really const!! + */ + diff --git a/src/scores.cc b/src/scores.cc new file mode 100644 index 0000000000..04efd6e4b1 --- /dev/null +++ b/src/scores.cc @@ -0,0 +1,34 @@ +#include "main.hh" +#include "score.hh" +#include "string.hh" + +static svec sv; + +static String outfn="lelie.uit"; + +// todo: check we don't overwrite default output. + +void +do_scores() +{ + for (int i=0; i < sv.sz(); i++) { + sv[i]->process(); + sv[i]->output(outfn); + delete sv[i]; + sv[i] =0; + } +} + +void +add_score(Score * s) +{ + sv.add(s); +} + + +void +set_default_output(String s) +{ + outfn = s; +} + diff --git a/src/simpleprint.cc b/src/simpleprint.cc new file mode 100644 index 0000000000..395396e22b --- /dev/null +++ b/src/simpleprint.cc @@ -0,0 +1,55 @@ +#include "lookup.hh" +#include "request.hh" +#include "beam.hh" +#include "pscore.hh" +#include "paper.hh" +#include "simplestaff.hh" +#include "molecule.hh" +#include "sccol.hh" +#include "stem.hh" +#include "notehead.hh" +#include "rest.hh" +#include "debug.hh" +#include "bar.hh" +#include "meter.hh" + +Item * +Simple_staff::get_TYPESET_item(Command *com) +{ + Item *s; + if (com -> args[0] == "BAR" ) { + s = new Bar(com->args[1]); + } else if (com->args[0] == "METER") { + svec arg( com->args); + arg.del(0); + s = new Meter(arg); + } else + assert(false); + + return s; +} + +void +Simple_column::typeset_item(Item *i, int breakst) +{ + assert(i); + // ugh + staff_->pscore_->typeset_item(i, score_column->pcol, + staff_->theline,breakst); +} + +void +Simple_staff::set_output(PScore* ps ) +{ + pscore_ = ps; + pscore_->add(theline); +} + + +Rest* +Simple_staff::get_rest(Rest_req*rq) +{ + int b = rq->rhythmic()->balltype; + int d = rq->rhythmic()->dots; + return new Rest(b, d); +} diff --git a/src/simplestaff.cc b/src/simplestaff.cc new file mode 100644 index 0000000000..5150d5478a --- /dev/null +++ b/src/simplestaff.cc @@ -0,0 +1,66 @@ +#include "request.hh" +#include "swalker.hh" +#include "debug.hh" +#include "staff.hh" +#include "command.hh" +#include "simplestaff.hh" +#include "sccol.hh" + + + + +Simple_column::Simple_column(Score_column*s, Simple_staff *rs) + : Staff_column(s) +{ + stem_ = 0; + staff_ = rs; + beam_ = 0; +} + +Simple_staff::Simple_staff() +{ + theline = 0; +} + +/** + accept: + + BREAK: all + TYPESET: bar, meter, + + */ + + + +void +Simple_column::process_requests() +{ + for (int i = 0 ; i < v_elts.sz(); i ++) + for (PCursor rqc(v_elts[i]->reqs); rqc.ok(); rqc++) { + Request *rq= rqc; + if (rq->rhythmic()){ + notes.add( rq->rhythmic()); + } + if (rq->stem()) { + stem_ = rq->stem(); + } + + if (rq->beam()) { + beam_ = rq->beam(); + } + } +} +Staff_column* +Simple_staff::create_col(Score_column*s) +{ + return new Simple_column(s,this); +} +void +Simple_staff::walk() +{ + for (Simple_walker sc(this); sc.ok(); sc++) { + sc.col()->process_requests();// TODO + sc.process(); + } +} + diff --git a/src/simplewalker.cc b/src/simplewalker.cc new file mode 100644 index 0000000000..ad9019ac33 --- /dev/null +++ b/src/simplewalker.cc @@ -0,0 +1,106 @@ +#include "request.hh" +#include "beam.hh" +#include "pscore.hh" +#include "simplestaff.hh" +#include "sccol.hh" +#include "stem.hh" +#include "notehead.hh" +#include "rest.hh" +#include "debug.hh" + +void +Simple_walker::process_command(Command*com) +{ + switch (com->code){ + case BREAK_PRE: + case BREAK_MIDDLE: + case BREAK_POST: + case BREAK_END: + (*this)->score_column->set_breakable(); + break_status = com->code- BREAK_PRE; + break; + case INTERPRET: + break; + + case TYPESET: + { + Item* i = staff()->get_TYPESET_item(com); + col()->typeset_item(i, break_status); + } + break; + + default : + break; + } +} + +void +Simple_walker::process_requests() +{ + Simple_column*c = col(); + Simple_staff *s = staff(); + if (c->beam_&& c->beam_->spantype == Span_req::START) { + if (beam_) + error("Too many beams"); + beam_ = new Beam; + } + + if (c->stem_) { + stem_ = s->get_stem(c->stem_->stem()); + c->typeset_item(stem_); + } + + for (int i = 0; i < c->notes.sz(); i ++) { + Rhythmic_req*rq = c->notes[i]; + if (rq->note()) { + Notehead*n = s->get_notehead(rq->note()); + stem_->add(n); + noteheads.add(n); + } + + if (rq->rest()) { + c->typeset_item( s->get_rest(rq->rest()) ); + } + } + + + if (beam_) { + beam_->add(stem_); + } + + if (c->beam_&& c->beam_->spantype == Span_req::STOP) { + pscore_->typeset_spanner(beam_, s->theline); + beam_ = 0; + } + for (int i = 0; i < noteheads.sz(); i++) { + c->typeset_item(noteheads[i]); + } + noteheads.set_size(0); + + if (stem_) { + stem_ = 0; + } +} + +Simple_walker::Simple_walker(Simple_staff*s) + : Staff_walker(s, s->theline->pscore_) +{ + stem_ = 0; + beam_ =0; +} + + + +Simple_staff* +Simple_walker::staff() +{ + return (Simple_staff*) staff_; +} + +Simple_column* +Simple_walker::col() +{ + return (Simple_column*) *(*this); +} + + diff --git a/src/spanner.cc b/src/spanner.cc new file mode 100644 index 0000000000..16c3ff19cb --- /dev/null +++ b/src/spanner.cc @@ -0,0 +1,54 @@ +#include "pstaff.hh" +#include "debug.hh" +#include "pscore.hh" +#include "spanner.hh" +#include "symbol.hh" +#include "molecule.hh" +#include "pcol.hh" + +String +Spanner::TeXstring() const +{ + + assert(output); + return output->TeXstring(); +} + +Spanner::Spanner() +{ + pstaff_=0; + left = right = 0; +} + +void +Spanner::process() +{ +} + +void +Spanner::preprocess() +{ +} + +Interval +Spanner::width()const +{ + return Interval(0,right->hpos - left->hpos); +} + +Paperdef* +Spanner::paper()const +{ + assert(pstaff_); + return pstaff_->pscore_->paper_; +} +void +Spanner::print()const +{ +#ifndef NPRINT + mtor << "Spanner { Output "; + output->print(); + + mtor << "}\n"; +#endif +} diff --git a/src/staff.cc b/src/staff.cc new file mode 100644 index 0000000000..3a32801b2f --- /dev/null +++ b/src/staff.cc @@ -0,0 +1,172 @@ +#include "staff.hh" +#include "swalker.hh" +#include "stcol.hh" +#include "sccol.hh" +#include "debug.hh" + +Staff::Staff(Staff const&src) +{ + PL_copy(voices,src.voices); + PL_copy(commands,src.commands); + assert(!cols.size()); // cols is a runtime field. + + score_ = src.score_; + pscore_ = src.pscore_; +} + +Paperdef* +Staff::paper() const{ + return score_->paper_; +} + +void +Staff::clean_cols() +{ + PCursor stc(cols); + for(; stc.ok(); ){ + if (!stc->score_column->used()) + stc.del(); + else + stc++; + } +} + +Staff_column * +Staff::get_col(Real w, bool mus) +{ + Score_column* sc = score_->find_col(w,mus); + assert(sc->when == w); + PCursor stc(cols); + for (; stc.ok(); stc++) { + if (*stc->score_column > *sc) // too far + break; + if (sc == stc->score_column) + return stc; + } + Staff_column* newst = create_col(sc); + + if (!stc.ok()) { + cols.bottom().add(newst); + return cols.bottom(); + } + + if (mus) { + stc.insert(newst); + return newst; + } + + if ((stc-1)->when() == newst->when()) { + stc--; + } + + stc.insert(newst); + + return newst; +} + + +void +Staff::add_voice(Voice *v) +{ + voices.bottom().add(v); +} + +/* + put all stuff grouped vertically in the Staff_cols + */ +void +Staff::setup_staffcols() +{ + + for (PCursor vc(voices); vc.ok(); vc++) { + + Real now = vc->start; + for (PCursor ve(vc->elts); ve.ok(); ve++) { + + Staff_column *sc=get_col(now,true); + sc->add(ve); + now += ve->duration; + } + } + + for (PCursor cc(commands); cc.ok(); cc++) { + Staff_column *sc=get_col(cc->when,false); + sc->s_commands.add(cc); + } +} + +/// merge commands from score +void +Staff::add_commands(PointerList const &cl) +{ + PCursor score_c(cl); + PCursor cc(commands); + + while (score_c.ok()) { + while (cc.ok() && cc->when <= score_c->when) + cc++; + + Command*nc = new Command (*(* score_c)); + if (cc.ok()) { + // cc->when > score_c->when + cc.insert( nc ); + } else { + commands.bottom().add( nc); + cc = commands.bottom(); + } + score_c++; + } + + // now integrate break commands with other commands. + // maybe do this in derived functions. +} + +void +Staff::process() +{ + setup_staffcols(); + OK(); + walk(); +} + +void +Staff::OK() const +{ +#ifndef NDEBUG + cols.OK(); + commands.OK(); + voices.OK(); + assert(score_); +#endif +} + + +Real +Staff::last() const +{ + Real l = 0.0; + for (PCursor vc(voices); vc.ok(); vc++) { + l = MAX(l, vc->last()); + } + return l; +} + + +void +Staff::print() const +{ +#ifndef NPRINT + mtor << "Staff {\n"; + for (PCursor vc(voices); vc.ok(); vc++) { + vc->print(); + + } + mtor <<"}\n"; +#endif +} + +Staff::Staff() +{ + score_ =0; + pscore_=0; +} diff --git a/src/staffline.cc b/src/staffline.cc new file mode 100644 index 0000000000..c83e904bc6 --- /dev/null +++ b/src/staffline.cc @@ -0,0 +1,107 @@ +#include "staffline.hh" +#include "scoreline.hh" +#include "dimen.hh" +#include "spanner.hh" +#include "symbol.hh" +#include "paper.hh" +#include "pcol.hh" +#include "pscore.hh" + +static String +make_vbox(Interval i) +{ + String s("\\vbox to "); + s += print_dimen(i.length()); + s += "{\\vskip "+print_dimen(i.max)+" "; + return s; +} + + +String +Line_of_staff::TeXstring() const +{ + String s("%line_of_staff\n"); + s+=make_vbox(height()); + // the staff itself: eg lines, accolades + s += "\\hbox{"; + { + Symbol sym = pstaff_->get_stafsym(scor->score->paper_->linewidth); + s+=sym.tex; + PCursor cc(scor->cols); + Real lastpos=cc->hpos; + + // all items in the current line & staff. + for (; cc.ok(); cc++) { + Real delta=cc->hpos - lastpos; + lastpos = cc->hpos; + + // moveover + if (delta) + s +=String( "\\kern ") + print_dimen(delta); + + // now output the items. + + for (PCursor ic(cc->its); ic.ok(); ic++) { + if (ic->pstaff_ == pstaff_) + s += ic->TeXstring(); + } + // spanners. + for (PCursor sc(cc->starters); sc.ok(); sc++) + if (sc->pstaff_ == pstaff_) + s += sc->TeXstring(); + } + } + s+="\\hss}\\vss}"; + return s; +} + +Line_of_staff::Line_of_staff(Line_of_score * sc, PStaff*st) +{ + scor=sc; + pstaff_=st; +#if 0 + const PCol *linestart = sc->cols.top(); + const PCol *linestop = sc->cols.bottom(); + + for (PCursor sp(pstaff_->spans); sp.ok(); sp++) { + const PCol *brokenstart = &MAX(*linestart, *sp->left); + const PCol *brokenstop = &MIN(*linestop, *sp->right); +// if (*brokenstop < *brokenstart) + brokenspans.bottom().add(sp->broken_at(0,0)); + } +#endif + for (PCursor sp(pstaff_->spans); sp.ok(); sp++) { + + brokenspans.bottom().add(sp->broken_at(0,0)); + } +} + + +Interval +Line_of_staff::height() const +{ + Interval y; + { + Symbol s = pstaff_->stafsym->eval(scor->score->paper_->linewidth); + y = s.dim.y; + } + PCursor cc(scor->cols); + + // all items in the current line & staff. + for (; cc.ok(); cc++) { + for (PCursor ic(cc->its); ic.ok(); ic++) { + if (ic->pstaff_ == pstaff_) { + y.unite(ic->height()); + } + + // spanners. + for (PCursor sc(cc->starters); sc.ok(); sc++) + if (sc->pstaff_ == pstaff_) { + y.unite(sc->height()); + } + } + } + return y; +} + + diff --git a/src/stcol.cc b/src/stcol.cc new file mode 100644 index 0000000000..799daed316 --- /dev/null +++ b/src/stcol.cc @@ -0,0 +1,30 @@ +#include "stcol.hh" +#include "sccol.hh" +#include "voice.hh" + +bool +Staff_column::mus() const +{ + return score_column->musical; +} + +Real +Staff_column::when() const +{ + return score_column->when; +} + +void +Staff_column::add(Voice_element*ve) +{ + Real d= ve->duration; + if (d){ + score_column->durations.add(d); + } + + v_elts.add(ve); +} + +Staff_column::Staff_column(Score_column*s) { + score_column = s; +} diff --git a/src/stem.cc b/src/stem.cc new file mode 100644 index 0000000000..fdb47f9755 --- /dev/null +++ b/src/stem.cc @@ -0,0 +1,156 @@ +#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<<","< 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; +} diff --git a/src/swalker.cc b/src/swalker.cc new file mode 100644 index 0000000000..db48fd1f82 --- /dev/null +++ b/src/swalker.cc @@ -0,0 +1,32 @@ +#include "request.hh" +#include "swalker.hh" +#include "stcol.hh" + +Staff_walker::~Staff_walker() {} + +Staff_walker::Staff_walker(Staff * s, PScore*ps ) + : PCursor (s->cols) +{ + staff_ = s; + pscore_ = ps; + break_status = BREAK_END - BREAK_PRE; +} + +Real +Staff_walker::when() const +{ + return (* (PCursor *) this)->when(); +} + +void +Staff_walker::process() +{ + break_status = BREAK_END - BREAK_PRE; + + for (int i = 0 ; i < (*this)->s_commands.sz(); i++) { + process_command((*this)->s_commands[i]); + } + + process_requests(); +} + diff --git a/src/symbol.cc b/src/symbol.cc new file mode 100644 index 0000000000..907f1d7282 --- /dev/null +++ b/src/symbol.cc @@ -0,0 +1,32 @@ +#include "symbol.hh" + +Symbol::Symbol() + : dim(Interval(0,0),Interval(0,0)) +{ + tex = "\\unknown"; +} +Symbol::Symbol(String s, Box b) + : dim(b) +{ + tex = s; +} + +/****************************************************************/ + +Symbol +Parametric_symbol::eval(String args1)const +{ + svec a; + a.add(args1); + return eval(a); +} + +Symbol +Parametric_symbol::eval(String args1,String arg2)const +{ + svec a; + a.add(args1); + a.add(arg2); + return eval(a); +} + diff --git a/src/symtable.cc b/src/symtable.cc new file mode 100644 index 0000000000..a28d14670c --- /dev/null +++ b/src/symtable.cc @@ -0,0 +1,60 @@ +#include "misc.hh" +#include "dimen.hh" +#include "debug.hh" +#include "real.hh" +#include "symbol.hh" +#include "assoc.hh" +#include "symtable.hh" + + +Symbol +Symtable::lookup(String s) const +{ + if (elt_query(s)) + return (*this)[s]; + else { + error( "Unknown symbol " +s+'\n'); + } +} + +Symtable* +Symtables::operator()(String s) +{ + return Assoc::operator[](s); +} + +void +Symtables::read(Text_db &symini) +{ + while (!symini.eof()) { + Text_record r( symini++); + if (r[0] == "end" ) + return; + assert (r[0] == "table"); + + String tabnam = r[1]; + Symtable * sp = new Symtable; + while (!symini.eof()){ + r = symini++; + if (r[0] == "end") + break; + + if (r.sz() != 6) + error("Not enough fields in symbol init"); + + int i=0; + String id=r[i++]; + String tex=r[i++]; + svec dims; + for (int j=0; j < 4; j++) + dims.add( parse_dimen(r[i++])); + + Symbol s(tex, Box(dims)); + (*sp)[id] = s; + } + (*this)[tabnam] = sp; + } +} + + + diff --git a/src/table.cc b/src/table.cc new file mode 100644 index 0000000000..1f302259e9 --- /dev/null +++ b/src/table.cc @@ -0,0 +1,67 @@ +#include "glob.hh" +#include "debug.hh" +#include "string.hh" +#include "identifier.hh" +#include "keyword.hh" +#include "associter.hh" +#include "parser.hh" + +static Keyword_ent the_key_tab[]={ + "voice", VOICE, + "rhythmstaff", RHYTHMSTAFF, + "melodicstaff", MELODICSTAFF, + "score", SCORE, + "bar", BAR, + "output", OUTPUT, + "cm", CM, + "start", START_T, + "pt", PT, + "in", IN, + "mm", MM, + "paper", PAPER, + "width", WIDTH, + "meter", METER, + "unitspace", UNITSPACE, + "skip", SKIP, + "octave", OCTAVECOMMAND, + "commands", COMMANDS, + "staff", STAFF, + "geometric", GEOMETRIC, + "duration", DURATIONCOMMAND, + 0,0 +} ; + + +int +lookup_keyword(String s) +{ + static Keyword_table table(the_key_tab); + return table.lookup(s); +} + +Assoc the_id_tab; + +Identifier* +lookup_identifier(String s) +{ + if (!the_id_tab.elt_query(s)) + return 0; + + return the_id_tab[s]; +} + +void +add_identifier(Identifier*i) +{ + the_id_tab[i->name] = i; +} + +void +delete_identifiers() +{ + + for (Assoc_iter ai(the_id_tab); ai.ok(); ai++) { + mtor << "deleting: " << ai.key()<<'\n'; + delete ai.val(); + } +} diff --git a/src/template1.cc b/src/template1.cc new file mode 100644 index 0000000000..fd2431130e --- /dev/null +++ b/src/template1.cc @@ -0,0 +1,25 @@ + +#include "plist.hh" +#include "pcol.hh" +#include "item.hh" +#include "request.hh" +#include "command.hh" +#include "spanner.hh" +#include "scoreline.hh" +#include "staffline.hh" + +#include "list.cc" +#include "plist.cc" +#include "cursor.cc" + +#define PLC_instantiate(a) PL_instantiate(a); PL_instantiate(const a) + +L_instantiate(Stem*); +PLC_instantiate(Line_of_score); +PLC_instantiate(Line_of_staff); +PLC_instantiate(Item); +PLC_instantiate(Spanner); +PLC_instantiate(PStaff); +PLC_instantiate(Idealspacing); +PLC_instantiate(PCol); + diff --git a/src/template2.cc b/src/template2.cc new file mode 100644 index 0000000000..01695c863f --- /dev/null +++ b/src/template2.cc @@ -0,0 +1,19 @@ + +#include "symbol.hh" +#include "voice.hh" + +#include "staff.hh" +#include "sccol.hh" +#include "stcol.hh" +#include "spanner.hh" + +#include "list.cc" +#include "plist.cc" +#include "cursor.cc" +PL_instantiate(Score_column); +PL_instantiate(Staff_column); +PL_instantiate(Staff); +PL_instantiate(Voice_element); +PL_instantiate(Voice); + + diff --git a/src/template3.cc b/src/template3.cc new file mode 100644 index 0000000000..92921bb29a --- /dev/null +++ b/src/template3.cc @@ -0,0 +1,12 @@ +#include "request.hh" +#include "command.hh" +#include "molecule.hh" +#include "list.cc" +#include "plist.cc" +#include "cursor.cc" +PL_instantiate(Atom); +PL_instantiate(Command); +PL_instantiate(Request); + + + diff --git a/src/tex.cc b/src/tex.cc new file mode 100644 index 0000000000..ae9dc1b5f3 --- /dev/null +++ b/src/tex.cc @@ -0,0 +1,32 @@ +#include "dimen.hh" +#include "tex.hh" +#include "symbol.hh" +#include "const.hh" + +String +vstrut(Real h) +{ + return String("\\vrule height ") + print_dimen(h) + "depth 0pt width 0pt"; +} + + +static void +substitute_arg(String& r, String arg) +{ + int p = r.pos('%'); + if (!p ) return ; + else p--; + r = r.left(p) + arg + r.right(r.len() - p -1); +} + + +String +substitute_args(String source, svec args) +{ + String retval (source); + for (int i = 0 ; i < args.sz(); i++) + substitute_arg(retval, args[i]); + while (retval.pos('%')) + substitute_arg(retval, ""); + return retval; +} diff --git a/src/texbeam.cc b/src/texbeam.cc new file mode 100644 index 0000000000..e21efba0be --- /dev/null +++ b/src/texbeam.cc @@ -0,0 +1,99 @@ +/* + + Code to generate beams for TeX + + */ + + #include +#include "symbol.hh" +#include "molecule.hh" +#include "tex.hh" +#include "symtable.hh" +#include "dimen.hh" +#include "lookup.hh" + +Symbol +Lookup::beam_element(int sidx, int widx, Real slope) +{ + Symbol bs=(*symtables_)("beamslopes")->lookup("slope"); + + svec args; + args.add(sidx); + args.add(widx); + bs.tex = substitute_args(bs.tex,args); + int w = 2 << widx; + Real width = convert_dimen(w,"pt"); + bs.dim.x = Interval(0,width); + bs.dim.y = Interval(0,width*slope); + return bs; +} + +// ugh.. hard wired tex-code. +static int +slope_index(Real &s) +{ + assert(ABS(s) < 0.45); + int i = int(rint(s * 20.0)); + + s = i/20.0; + if (s>0) + return 6*i +122; + else + return -6 * i+ 188; +} + +Symbol +Lookup::rule_symbol(Real height, Real width) +{ + Symbol bs=(*symtables_)("beamslopes")->lookup("horizontal"); + svec args; + args.add(print_dimen(height)); + args.add(print_dimen(width)); + bs.tex = substitute_args(bs.tex,args); + bs.dim.x = Interval(0,width); + bs.dim.y = Interval(0,height); + return bs; +} + +Symbol +Lookup::beam(Real &slope, Real width) +{ + int sidx = slope_index(slope); + if (!slope) + return rule_symbol(convert_dimen(2,"pt"), width); + + Real w = width; + Real elemwidth = convert_dimen(64,"pt"); + int widx = 5; + + Molecule m; + Real dy=0; + Real minwid =convert_dimen(2,"pt"); + assert(w > minwid); + while (w > minwid) { + while (elemwidth > w) { + widx --; + elemwidth /= 2.0; + } + + Atom a(beam_element(sidx, widx, slope)); + a.translate(Offset(0, dy)); + m.add_right(a); + dy += elemwidth*slope; + w -= elemwidth; + } + + widx = 0; + Atom a(beam_element(sidx, widx, slope)); + a.translate(Offset(width -minwid, (width-minwid) * slope)); + m.add(a); + + Symbol ret; + ret.tex = m.TeXstring(); + ret.dim.y = Interval(0,width*slope); + ret.dim.x = Interval(0,width); + + return ret; +} + + diff --git a/src/tstream.cc b/src/tstream.cc new file mode 100644 index 0000000000..05e2e9c93e --- /dev/null +++ b/src/tstream.cc @@ -0,0 +1,75 @@ +#include +#include +#include "tex.hh" +#include "main.hh" +#include "tstream.hh" +#include "debug.hh" + +Tex_stream::Tex_stream(String filename) +{ + os = new ofstream(filename); + if (!*os) + error("can't open `" + filename+"\'"); + nest_level = 0; + outputting_comment=false; + header(); +} +void +Tex_stream::header() +{ + *os << "% Creator: " << get_version(); + *os << "% Automatically generated, at "; + time_t t(time(0)); + *os << ctime(&t); +//*os << "% from input file ..\n"; +} +Tex_stream::~Tex_stream() +{ + delete os; + assert(nest_level == 0); +} + +// 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; + if (*cp == '\n') { + outputting_comment=false; + + } + continue; + } + switch(*cp) + { + case '%': + outputting_comment = true; + *os << *cp; + break; + case '{': + nest_level++; + *os << *cp; + break; + case '}': + nest_level--; + *os << *cp; + assert (nest_level >= 0); + /* FALTHROUGH */ + + case '\n': + *os << "%\n"; + *os << String(' ', nest_level); + break; + default: + *os << *cp; + break; + } + } + return *this; +} + + +/****************************************************************/ diff --git a/src/version.cc b/src/version.cc new file mode 100644 index 0000000000..401273b6b1 --- /dev/null +++ b/src/version.cc @@ -0,0 +1,9 @@ +#include "version.hh" + +static char *s = "LilyPond version " VERSIONSTR " compiled on " __DATE__ " at " __TIME__ "\n"; + +const char * +get_version() +{ + return s; +} diff --git a/src/voice.cc b/src/voice.cc new file mode 100644 index 0000000000..14883e1499 --- /dev/null +++ b/src/voice.cc @@ -0,0 +1,78 @@ +#include "debug.hh" +#include "voice.hh" + +Voice::Voice(Voice const&src) +{ + PL_copy(elts, src.elts); + start = src.start; +} + +Voice::Voice() +{ + start = 0.0; +} + +void +Voice::add(Voice_element*v) +{ + elts.bottom().add(v); +} + +void +Voice::print() const +{ + #ifndef NPRINT + + mtor << "start: "<< start< vec(elts); vec.ok(); vec++) + vec->print(); +#endif +} + +Real +Voice::last() const +{ + Real l =start; + for (PCursor vec(elts); vec.ok(); vec++) + l += vec->duration; + return l; +} +/****************************************************************/ +void +Voice_element::print() const +{ +#ifndef NPRINT + mtor << "voice_element { dur :"<< duration <<"\n"; + for (PCursor rc(reqs); rc.ok(); rc++) { + rc->print(); + } + mtor << "}\n"; +#endif +} +void +Voice_element::add(Request*r) +{ + if (r->rhythmic()) { + assert (!duration); + duration = r->duration(); + } + r->elt = this; + reqs.bottom().add(r); +} + + +Voice_element::Voice_element() +{ + voice = 0; + group = 0; + duration = 0.0; +} + +Voice_element::Voice_element(Voice_element const&src) +{ + duration=src.duration; + voice=src.voice; + PointerList__copy(Request*, reqs, src.reqs, clone()); + group=src.group; + assert(!granted_items.size() && !granted_spanners.size()); +} diff --git a/src/warn.cc b/src/warn.cc new file mode 100644 index 0000000000..426173ee0c --- /dev/null +++ b/src/warn.cc @@ -0,0 +1,18 @@ +#include "debug.hh" + ostream &warnout (cerr); + ostream *mlog(&cerr); + + + +void warning(String s) +{ + WARN << s; +} + + +void error(String s) +{ + cerr << "\n" << s << "\nexiting..\n"; + exit(1); +} + diff --git a/staff.cc b/staff.cc deleted file mode 100644 index 8b5c0782c5..0000000000 --- a/staff.cc +++ /dev/null @@ -1,175 +0,0 @@ -#include "staff.hh" -#include "stcol.hh" -#include "sccol.hh" -#include "debug.hh" - -Staff::Staff(Staff const&src) -{ - PL_copy(voices,src.voices); - PL_copy(commands,src.commands); - assert(!cols.size()); // cols is a runtime field. - - score_ = src.score_; - pscore_ = src.pscore_; -} - -Paperdef* -Staff::paper() const{ - return score_->paper_; -} - -void -Staff::clean_cols() -{ - PCursor stc(cols); - for(; stc.ok(); ){ - if (!stc->score_column->used()) - stc.del(); - else - stc++; - } -} - -Staff_column * -Staff::get_col(Real w, bool mus) -{ - Score_column* sc = score_->find_col(w,mus); - assert(sc->when == w); - PCursor stc(cols); - for (; stc.ok(); stc++) { - if (*stc->score_column > *sc) // too far - break; - if (sc == stc->score_column) - return stc; - } - Staff_column* newst = create_col(sc); - - if (!stc.ok()) { - cols.bottom().add(newst); - return cols.bottom(); - } - - if (mus) { - stc.insert(newst); - return newst; - } - - if ((stc-1)->when() == newst->when()) { - stc--; - } - - stc.insert(newst); - - return newst; -} - - -void -Staff::add_voice(Voice *v) -{ - voices.bottom().add(v); -} - -/* - put all stuff grouped vertically in the Staff_cols - */ -void -Staff::setup_staffcols() -{ - - for (PCursor vc(voices); vc.ok(); vc++) { - - Real now = vc->start; - for (PCursor ve(vc->elts); ve.ok(); ve++) { - - Staff_column *sc=get_col(now,true); - sc->add(ve); - now += ve->duration; - } - } - - for (PCursor cc(commands); cc.ok(); cc++) { - Staff_column *sc=get_col(cc->when,false); - sc->s_commands.add(cc); - } -} - -/// merge commands from score -void -Staff::add_commands(PointerList const &cl) -{ - PCursor score_c(cl); - PCursor cc(commands); - - while (score_c.ok()) { - while (cc.ok() && cc->when <= score_c->when) - cc++; - - Command*nc = new Command (*(* score_c)); - if (cc.ok()) { - // cc->when > score_c->when - cc.insert( nc ); - } else { - commands.bottom().add( nc); - cc = commands.bottom(); - } - score_c++; - } - - // now integrate break commands with other commands. - // maybe do this in derived functions. -} - -void -Staff::process() -{ - setup_staffcols(); - OK(); - for (PCursor sc(cols); sc.ok(); sc++) { - sc->process_commands(); - sc->process_requests(); - } - grant_requests(); -} - -void -Staff::OK() const -{ -#ifndef NDEBUG - cols.OK(); - commands.OK(); - voices.OK(); - assert(score_); -#endif -} - - -Real -Staff::last() const -{ - Real l = 0.0; - for (PCursor vc(voices); vc.ok(); vc++) { - l = MAX(l, vc->last()); - } - return l; -} - - -void -Staff::print() const -{ -#ifndef NPRINT - mtor << "Staff {\n"; - for (PCursor vc(voices); vc.ok(); vc++) { - vc->print(); - - } - mtor <<"}\n"; -#endif -} - -Staff::Staff() -{ - score_ =0; - pscore_=0; -} diff --git a/staff.hh b/staff.hh deleted file mode 100644 index f2c7294de0..0000000000 --- a/staff.hh +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef STAFF_HH -#define STAFF_HH - -#include "score.hh" -#include "voice.hh" -#include "command.hh" - - -/// base class for a collection of voices. -struct Staff { - /// synchronous horizontal stuff - PointerList voices; - - /// commands in chronological order - PointerList commands; - - /// runtime field - PointerList cols; - - /// indirections to the Score and PScore - Score *score_; - PScore *pscore_; - - /****************************************************************/ - Staff(const Staff&src); - void add_voice(Voice *v); - void add_staff_column(Staff_column *sp); - - Paperdef*paper()const; - /// interpret all requests and add items to #destination#. - void process(); - /** - This routines calls virtual functions from Staff, to delegate the - interpretation of requests to a derived class of Staff */ - void setup_staffcols(); - - void OK() const; - void print() const; - Real last() const; - void clean_cols() ; - Staff_column * get_col(Real,bool); - - void add_commands(PointerListconst & sv); - /** - add all commands from sv. - - PRE - sv is time-ordered. - */ - - Staff(); - /** - Should construct with Score as arg, but this isn't known during parsing. - */ - /**************************************************************** - VIRTUALS - ****************************************************************/ - virtual Staff*clone()const=0; - virtual void set_output(PScore * destination)=0; - virtual void grant_requests()=0; - virtual Staff_column * create_col(Score_column * )=0; - virtual ~Staff() { } -}; -#endif - - diff --git a/stcol.cc b/stcol.cc deleted file mode 100644 index 799daed316..0000000000 --- a/stcol.cc +++ /dev/null @@ -1,30 +0,0 @@ -#include "stcol.hh" -#include "sccol.hh" -#include "voice.hh" - -bool -Staff_column::mus() const -{ - return score_column->musical; -} - -Real -Staff_column::when() const -{ - return score_column->when; -} - -void -Staff_column::add(Voice_element*ve) -{ - Real d= ve->duration; - if (d){ - score_column->durations.add(d); - } - - v_elts.add(ve); -} - -Staff_column::Staff_column(Score_column*s) { - score_column = s; -} diff --git a/stcol.hh b/stcol.hh deleted file mode 100644 index 1d8b09c61e..0000000000 --- a/stcol.hh +++ /dev/null @@ -1,35 +0,0 @@ -/* - stcol.hh -- part of LilyPond - - (c) 1996 Han-Wen Nienhuys -*/ - -#ifndef STCOL_HH -#define STCOL_HH -#include "proto.hh" -#include "vray.hh" - -/// store simultaneous requests -struct Staff_column { - Score_column *score_column; - - /// fields to collect data vertically. - svec v_elts; - svec s_commands; - - Staff_column(Score_column*s); - bool mus() const; - Real when() const; - void add(Voice_element*ve); - /**************************************************************** - VIRTUAL - ****************************************************************/ - //virtual Staff_column *clone() const=0; - virtual void process_requests()=0; - virtual void process_commands()=0; - virtual ~Staff_column() { } -}; - - -#endif // STCOL_HH - diff --git a/stem.cc b/stem.cc deleted file mode 100644 index fd6634c6bf..0000000000 --- a/stem.cc +++ /dev/null @@ -1,99 +0,0 @@ -#include "stem.hh" -#include "dimen.hh" -#include "debug.hh" -#include "pstaff.hh" -#include "pscore.hh" -#include "paper.hh" -#include "lookupsyms.hh" -#include "molecule.hh" - -const int STEMLEN=7; - -Stem::Stem(int c) -{ - minnote = maxnote = 0; - bot = top = 0; - flag = 4; - staff_center=c; -} - -void -Stem::print()const -{ - mtor << "Stem minmax=["<< minnote<<","< stafftop + 2) { - top = maxnote; - bot = staff_center + staff_center/2; - flag = -flag; - }else { - Real mean = (minnote+maxnote)/2; - - top = (mean > staff_center) ? maxnote : maxnote+STEMLEN; - bot = (mean > staff_center) ? minnote-STEMLEN : minnote; - flag = (mean > staff_center) ? -flag : flag; - } -} - -void -Stem::postprocess() -{ - calculate(); - brew_molecole(); -} - -Interval -Stem::width()const -{ - if (ABS(flag) <= 4) - return Interval(0,0); // TODO! - Paperdef*p= pstaff_->pscore_->paper_; - return p->lookup_->flag(flag).dim.x; -} - -void -Stem::brew_molecole() -{ - assert(pstaff_); - 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){ - 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); - } - - if (flag > 0){ - Real dx = pstaff_->pscore_->paper_->note_width(); // ugh - output->translate(Offset(dx,0)); - } -} diff --git a/stem.hh b/stem.hh deleted file mode 100644 index acbebe0d92..0000000000 --- a/stem.hh +++ /dev/null @@ -1,44 +0,0 @@ -/* - stem.hh -- part of LilyPond - - (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; - - int staff_center; - - // extent of the stem (positions) - int bot, top; - - // flagtype? 4 none, 8 8th flag, 0 = beam. - int flag; - - /****************/ - - void postprocess(); - Stem(int center); - void print() 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 diff --git a/suzan.ly b/suzan.ly deleted file mode 100644 index 59eb0c7489..0000000000 --- a/suzan.ly +++ /dev/null @@ -1,8 +0,0 @@ -% testje - -score{ - rhythmstaff { - voice { $ c2 c2 c4. c8 c4 c4 c4 c4 c4 c4 c2 c2$ } - } - commands { meter 2 4 skip 2:0 meter 4 4 skip 2:0} -} diff --git a/symbol.cc b/symbol.cc deleted file mode 100644 index 907f1d7282..0000000000 --- a/symbol.cc +++ /dev/null @@ -1,32 +0,0 @@ -#include "symbol.hh" - -Symbol::Symbol() - : dim(Interval(0,0),Interval(0,0)) -{ - tex = "\\unknown"; -} -Symbol::Symbol(String s, Box b) - : dim(b) -{ - tex = s; -} - -/****************************************************************/ - -Symbol -Parametric_symbol::eval(String args1)const -{ - svec a; - a.add(args1); - return eval(a); -} - -Symbol -Parametric_symbol::eval(String args1,String arg2)const -{ - svec a; - a.add(args1); - a.add(arg2); - return eval(a); -} - diff --git a/symbol.hh b/symbol.hh deleted file mode 100644 index 4f26e04e66..0000000000 --- a/symbol.hh +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SYMBOL_HH -#define SYMBOL_HH -#include "string.hh" -#include "boxes.hh" -#include "proto.hh" - -struct Symbol { - String tex; - Box dim; - - Symbol (String, Box); - Symbol(); -}; - -struct Parametric_symbol { - Symtables*symtables_; // indirection - - /*****************/ - - Parametric_symbol(Symtables*s) { symtables_ = s; } - Symbol eval(String args1) const; // convenience - Symbol eval(String args1,String arg2) const; // convenience - virtual Symbol eval(svec args)const =0; - virtual ~Parametric_symbol(){} -}; - -#endif diff --git a/symbol.ini b/symbol.ini index ea303b04f1..e1e2f3f2a0 100644 --- a/symbol.ini +++ b/symbol.ini @@ -14,8 +14,8 @@ table balls end table streepjes - toplines \toplines{%} -6pt 6pt 0pt 0pt - botlines \botlines{%} -6pt 6pt 0pt 0pt + toplines \toplines{%} -7pt 7pt 0pt 0pt + botlines \botlines{%} -7pt 7pt 0pt 0pt end table bars @@ -56,9 +56,14 @@ table flags 8 \eigthflag 0pt 5pt 0pt 0pt 16 \sixteenthflag 0pt 5pt 0pt 0pt 32 \thirtysecondflag 0pt 5pt 0pt 0pt - -8 \ieigthflag -5pt 0pt 0pt 0pt - -16 \isixteenthflag -5pt 0pt 0pt 0pt - -32 \ithirtysecondflag -5pt 0pt 0pt 0pt + -8 \deigthflag 0pt 5pt 0pt 0pt + -16 \dsixteenthflag 0pt 5pt 0pt 0pt + -32 \dthirtysecondflag 0pt 5pt 0pt 0pt +end + +table beamslopes + slope \beamslope{%}{%} 0pt 0pt 0pt 0pt + horizontal \rulesym{%}{%} 0pt 0pt 0pt 0pt end end # symboltables \ No newline at end of file diff --git a/symtable.cc b/symtable.cc deleted file mode 100644 index e963b64d12..0000000000 --- a/symtable.cc +++ /dev/null @@ -1,58 +0,0 @@ -#include "misc.hh" -#include "dimen.hh" -#include "debug.hh" -#include "real.hh" -#include "symbol.hh" -#include "assoc.hh" -#include "symtable.hh" - - -Symbol -Symtable::lookup(String s) const -{ - if (elt_query(s)) - return (*this)[s]; - else { - error( "Unknown symbol " +s+'\n'); - } -} - -Symtable* -Symtables::operator()(String s) -{ - return Assoc::operator[](s); -} - -void -Symtables::read(Text_db &symini) -{ - while (!symini.eof()) { - Text_record r( symini++); - if (r[0] == "end" ) - return; - assert (r[0] == "table"); - - String tabnam = r[1]; - Symtable * sp = new Symtable; - while (!symini.eof()){ - r = symini++; - if (r[0] == "end") - break; - - assert(r.sz() == 6); - int i=0; - String id=r[i++]; - String tex=r[i++]; - svec dims; - for (int j=0; j < 4; j++) - dims.add( parse_dimen(r[i++])); - - Symbol s(tex, Box(dims)); - (*sp)[id] = s; - } - (*this)[tabnam] = sp; - } -} - - - diff --git a/symtable.hh b/symtable.hh deleted file mode 100644 index a1443a7d3b..0000000000 --- a/symtable.hh +++ /dev/null @@ -1,23 +0,0 @@ -/* - lilypond, (c) 1996 Han-Wen Nienhuys -*/ -#ifndef SYMTABLE_HH -#define SYMTABLE_HH -#include "assoc.hh" -#include "string.hh" -#include "symbol.hh" - -struct Symtable : public Assoc { - Symbol lookup(String)const; -}; - - -struct Symtables : private Assoc { - void read(Text_db&) ; - Symtable* operator()(String s); - -}; - - -#endif - diff --git a/table.cc b/table.cc deleted file mode 100644 index 58d1c425e1..0000000000 --- a/table.cc +++ /dev/null @@ -1,64 +0,0 @@ -#include "glob.hh" -#include "debug.hh" -#include "string.hh" -#include "identifier.hh" -#include "keyword.hh" -#include "associter.hh" -#include "parser.hh" - -static Keyword_ent the_key_tab[]={ - "voice", VOICE, - "rhythmstaff", RHYTHMSTAFF, - "melodicstaff", MELODICSTAFF, - "score", SCORE, - "bar", BAR, - "output", OUTPUT, - "cm", CM, - "pt", PT, - "in", IN, - "mm", MM, - "paper", PAPER, - "width", WIDTH, - "meter", METER, - "unitspace", UNITSPACE, - "skip", SKIP, - "commands", COMMANDS, - "staff", STAFF, - "geometric", GEOMETRIC, - 0,0 -} ; - - -int -lookup_keyword(String s) -{ - static Keyword_table table(the_key_tab); - return table.lookup(s); -} - -Assoc the_id_tab; - -Identifier* -lookup_identifier(String s) -{ - if (!the_id_tab.elt_query(s)) - return 0; - - return the_id_tab[s]; -} - -void -add_identifier(Identifier*i) -{ - the_id_tab[i->name] = i; -} - -void -delete_identifiers() -{ - - for (Assoc_iter ai(the_id_tab); ai.ok(); ai++) { - mtor << "deleting: " << ai.key()<<'\n'; - delete ai.val(); - } -} diff --git a/template1.cc b/template1.cc deleted file mode 100644 index ece4e2ff18..0000000000 --- a/template1.cc +++ /dev/null @@ -1,23 +0,0 @@ -#include "line.hh" - -#include "plist.hh" -#include "pcol.hh" -#include "item.hh" -#include "request.hh" -#include "command.hh" -#include "spanner.hh" - -#include "list.cc" -#include "plist.cc" -#include "cursor.cc" - -#define PLC_instantiate(a) PL_instantiate(a); PL_instantiate(const a) - -PLC_instantiate(Line_of_score); -PLC_instantiate(Line_of_staff); -PLC_instantiate(Item); -PLC_instantiate(Spanner); -PLC_instantiate(PStaff); -PLC_instantiate(Idealspacing); -PLC_instantiate(PCol); - diff --git a/template2.cc b/template2.cc deleted file mode 100644 index 5e0431c42a..0000000000 --- a/template2.cc +++ /dev/null @@ -1,19 +0,0 @@ -#include "line.hh" -#include "symbol.hh" -#include "voice.hh" - -#include "staff.hh" -#include "sccol.hh" -#include "stcol.hh" -#include "spanner.hh" - -#include "list.cc" -#include "plist.cc" -#include "cursor.cc" -PL_instantiate(Score_column); -PL_instantiate(Staff_column); -PL_instantiate(Staff); -PL_instantiate(Voice_element); -PL_instantiate(Voice); - - diff --git a/template3.cc b/template3.cc deleted file mode 100644 index 92921bb29a..0000000000 --- a/template3.cc +++ /dev/null @@ -1,12 +0,0 @@ -#include "request.hh" -#include "command.hh" -#include "molecule.hh" -#include "list.cc" -#include "plist.cc" -#include "cursor.cc" -PL_instantiate(Atom); -PL_instantiate(Command); -PL_instantiate(Request); - - - diff --git a/tex.cc b/tex.cc deleted file mode 100644 index ae9dc1b5f3..0000000000 --- a/tex.cc +++ /dev/null @@ -1,32 +0,0 @@ -#include "dimen.hh" -#include "tex.hh" -#include "symbol.hh" -#include "const.hh" - -String -vstrut(Real h) -{ - return String("\\vrule height ") + print_dimen(h) + "depth 0pt width 0pt"; -} - - -static void -substitute_arg(String& r, String arg) -{ - int p = r.pos('%'); - if (!p ) return ; - else p--; - r = r.left(p) + arg + r.right(r.len() - p -1); -} - - -String -substitute_args(String source, svec args) -{ - String retval (source); - for (int i = 0 ; i < args.sz(); i++) - substitute_arg(retval, args[i]); - while (retval.pos('%')) - substitute_arg(retval, ""); - return retval; -} diff --git a/tex.hh b/tex.hh deleted file mode 100644 index 546797a7c1..0000000000 --- a/tex.hh +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef TEX_HH -#define TEX_HH - -#include "string.hh" -#include "boxes.hh" - -/// parameter substitution in TeXstrings -String -substitute_args(String source, svec args); -/** - this structure provides a simple macro mechanism: - - if source == "tex%bla%", then - eval({"X","Y"}) == "texXblaY" - */ - -/// #h# is in points -String vstrut(Real h); - - -#endif diff --git a/tstream.cc b/tstream.cc deleted file mode 100644 index 05e2e9c93e..0000000000 --- a/tstream.cc +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include -#include "tex.hh" -#include "main.hh" -#include "tstream.hh" -#include "debug.hh" - -Tex_stream::Tex_stream(String filename) -{ - os = new ofstream(filename); - if (!*os) - error("can't open `" + filename+"\'"); - nest_level = 0; - outputting_comment=false; - header(); -} -void -Tex_stream::header() -{ - *os << "% Creator: " << get_version(); - *os << "% Automatically generated, at "; - time_t t(time(0)); - *os << ctime(&t); -//*os << "% from input file ..\n"; -} -Tex_stream::~Tex_stream() -{ - delete os; - assert(nest_level == 0); -} - -// 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; - if (*cp == '\n') { - outputting_comment=false; - - } - continue; - } - switch(*cp) - { - case '%': - outputting_comment = true; - *os << *cp; - break; - case '{': - nest_level++; - *os << *cp; - break; - case '}': - nest_level--; - *os << *cp; - assert (nest_level >= 0); - /* FALTHROUGH */ - - case '\n': - *os << "%\n"; - *os << String(' ', nest_level); - break; - default: - *os << *cp; - break; - } - } - return *this; -} - - -/****************************************************************/ diff --git a/tstream.hh b/tstream.hh deleted file mode 100644 index 9474dd69a8..0000000000 --- a/tstream.hh +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef TSTREAM__HH -#define TSTREAM__HH - -#include -#include "string.hh" - -/// TeX output -struct Tex_stream { - bool outputting_comment; - ostream *os; - int nest_level; - - /// open a file for writing - Tex_stream(String filename); - void header(); - /// delegate conversion to string class. - Tex_stream &operator<<(String); - - /// close the file - ~Tex_stream(); -}; -/** - Use this class for writing to a TeX file. - It counts braces to prevent nesting errors, and - it will add a comment sign before each newline. - */ -#endif diff --git a/version.cc b/version.cc deleted file mode 100644 index 401273b6b1..0000000000 --- a/version.cc +++ /dev/null @@ -1,9 +0,0 @@ -#include "version.hh" - -static char *s = "LilyPond version " VERSIONSTR " compiled on " __DATE__ " at " __TIME__ "\n"; - -const char * -get_version() -{ - return s; -} diff --git a/voice.cc b/voice.cc deleted file mode 100644 index 379cbae23a..0000000000 --- a/voice.cc +++ /dev/null @@ -1,77 +0,0 @@ -#include "debug.hh" -#include "voice.hh" - -Voice::Voice(Voice const&src) -{ - PL_copy(elts, src.elts); - start = src.start; -} - -Voice::Voice() -{ - start = 0.0; -} - -void -Voice::add(Voice_element*v) -{ - elts.bottom().add(v); -} - -void -Voice::print() const -{ - #ifndef NPRINT - - mtor << "start: "<< start< vec(elts); vec.ok(); vec++) - vec->print(); -#endif -} - -Real -Voice::last() const -{ - Real l =start; - for (PCursor vec(elts); vec.ok(); vec++) - l += vec->duration; - return l; -} -/****************************************************************/ -void -Voice_element::print() const -{ -#ifndef NPRINT - mtor << "voice_element { dur :"<< duration <<"\n"; - for (PCursor rc(reqs); rc.ok(); rc++) { - rc->print(); - } - mtor << "}\n"; -#endif -} -void -Voice_element::add(Request*r) -{ - if (r->rhythmic()) { - assert (!duration); - duration = r->duration(); - } - reqs.bottom().add(r); -} - - -Voice_element::Voice_element() -{ - voice = 0; - group = 0; - duration = 0.0; -} - -Voice_element::Voice_element(Voice_element const&src) -{ - duration=src.duration; - voice=src.voice; - PointerList__copy(Request*, reqs, src.reqs, clone()); - group=src.group; - assert(!granted_items.size() && !granted_spanners.size()); -} diff --git a/voice.hh b/voice.hh deleted file mode 100644 index 7180ece99e..0000000000 --- a/voice.hh +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef VOICE_HH -#define VOICE_HH - - -#include "plist.hh" -#include "request.hh" - -/// class for horizontal stuff. -struct Voice { - PointerList elts; - Real start; - - /****************/ - Real when(const Voice_element*)const; - Real last() const; - Voice(); - Voice(Voice const&); - void add(Voice_element*); - void print() const; -}; -/** - - Voice is a ordered row of Voice_elements. It is strictly horizontal: - you cannot have two rhythmic elements running parallel in a Voice - - */ - -struct Voicegroup { - /// don't know how to identify these. -}; - -/// one horizontal bit. -struct Voice_element { - Real duration; - const Voicegroup *group; - const Voice *voice; - PointerList reqs; - - List granted_items; - List granted_spanners; - - /****************/ - - void add(Request*); - Voice_element(); - Voice_element(Voice_element const & src ); - void print ()const; -}; -/** Apart from being a container for the requests, Voice_element is - glue between related items and spanners, between requests and - (voice)groups - */ -#endif diff --git a/warn.cc b/warn.cc deleted file mode 100644 index 426173ee0c..0000000000 --- a/warn.cc +++ /dev/null @@ -1,18 +0,0 @@ -#include "debug.hh" - ostream &warnout (cerr); - ostream *mlog(&cerr); - - - -void warning(String s) -{ - WARN << s; -} - - -void error(String s) -{ - cerr << "\n" << s << "\nexiting..\n"; - exit(1); -} -