]> git.donarmstrong.com Git - lilypond.git/blob - src/break.cc
release: 0.0.18
[lilypond.git] / src / break.cc
1 /*
2     do calculations for breaking problem
3     
4     */
5 #include "paper.hh"
6 #include "linespace.hh"
7 #include "debug.hh"
8 #include "scoreline.hh"
9 #include "pscore.hh"
10
11 // construct an appropriate Spacing_problem and solve it. 
12 svec<Real>
13 PScore::solve_line(svec< PCol *> curline) const
14 {
15    Spacing_problem sp;
16
17    sp.add_column(curline[0], true, 0.0);
18    for (int i=1; i< curline.sz()-1; i++)
19        sp.add_column(curline[i]);
20    sp.add_column(curline.last(), true, paper_->linewidth);
21
22    // misschien  moeven uit Spacing_problem? 
23    for (PCursor<Idealspacing *> i(suz); i.ok(); i++) {
24        sp.add_ideal(i);
25    }
26    svec<Real> the_sol=sp.solve();
27    return the_sol;
28 }
29
30 bool
31 PScore::feasible(svec< PCol *> curline) const
32 {
33     Real l =0;
34     for (int i=0; i < curline.sz(); i++)
35         l +=curline[i]->width().length();
36     return l < paper_->linewidth;    
37 }
38
39 void
40 PScore::problem_OK() const
41 {
42     if (!cols.size())
43         error("PScore::problem_OK(): Score does not have any columns");
44     PCursor<PCol *> start(cols);
45     PCursor<PCol *> end (((PScore*)this)->cols.bottom());
46     
47     assert(start->breakable());    
48     assert(end->breakable());
49 }
50
51 struct Col_configuration {
52     svec< PCol*> line;
53     svec<Real> config;
54     Real energy;
55
56     Col_configuration() {
57         energy = INFTY;
58     }
59     void add( PCol*c) { line.add(c);}
60     void setsol(svec<Real> sol) {
61         config = sol;
62         energy = config.last();
63         config.pop();
64     }
65     void print() const {
66 #ifndef NPRINT
67         mtor << "energy : " << energy << '\n';
68         mtor << "line of " << config.sz() << " cols\n";
69 #endif
70     }
71 };
72
73 /// wordwrap type algorithm
74 /* el stupido. This should be done more accurately:
75
76    It would be nice to have a Dynamic Programming type of algorithm
77    similar to TeX's
78    
79     */
80
81 void
82 PScore::calc_breaking()
83 {
84     OK();
85     problem_OK();
86     PCursor<PCol *> curcol(cols);
87             
88     svec<PCol *> breakpoints(find_breaks());
89     assert(breakpoints.sz()>=2);
90     for (int i=0 ; i < breakpoints.sz() -1; ) {
91         Col_configuration minimum;
92         Col_configuration current;
93
94         // do  another line
95         PCol *post = breakpoints[i]->postbreak;
96         current.add( post);
97         curcol++;               // skip the breakable.
98         i++;
99
100         while (i < breakpoints.sz()) {
101
102             // add another measure.
103             while (breakpoints[i] != curcol.ptr()){
104                 
105                 current.add(curcol);
106                 curcol++;
107             }
108             current.add(breakpoints[i]->prebreak );
109             if (!feasible(current.line)) {
110                 if (!minimum.line.sz())
111                     error("sorry, this measure is too long");
112                 break;
113             }
114             current.setsol(solve_line(current.line));
115             current.print();
116             
117             if (current.energy < minimum.energy) {              
118                 minimum = current;         
119             } else {            // we're one col too far.
120                 i--;
121                 while (curcol.ptr() != breakpoints[i])
122                     curcol --;
123                 
124                 break;
125             }
126         
127             current.line.last()=breakpoints[i];
128             curcol ++;
129             i++;
130         }
131         mtor << "Adding line, next breakpoint " << i << '\n';
132         add_line(minimum.line, minimum.config); 
133     }
134 }
135