]> git.donarmstrong.com Git - lilypond.git/blob - lily/dot-configuration.cc
Merge branch 'lilypond/translation' of ssh://git.sv.gnu.org/srv/git/lilypond
[lilypond.git] / lily / dot-configuration.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1997--2010 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
6   LilyPond is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   LilyPond is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <cstdio>
21 #include "dot-configuration.hh"
22 #include "dot-formatting-problem.hh"
23 #include "staff-symbol-referencer.hh"
24
25
26 int
27 Dot_configuration::badness () const
28 {
29   int t = 0;
30   for (Dot_configuration::const_iterator i (begin ());
31        i != end (); i++)
32     {
33       int p = i->first;
34       int demerit = sqr (p - i->second.pos_) * 2;
35
36       int dot_move_dir = sign (p - i->second.pos_);
37       if (i->second.extremal_head_)
38         {
39           if (i->second.dir_
40               && dot_move_dir != i->second.dir_)
41             demerit += 3;
42           else if (dot_move_dir != UP)
43             demerit += 2;
44         }
45       else if (dot_move_dir != UP)
46         demerit += 1;
47
48       t += demerit;
49     }
50
51   return t;
52 }
53
54 void
55 Dot_configuration::print () const
56 {
57   printf ("dotconf { ");
58   for (Dot_configuration::const_iterator i (begin ());
59        i != end (); i++)
60     printf ("%d, ", i->first);
61   printf ("}\n");
62 }
63
64 /*
65   Shift K and following (preceding) entries up (down) as necessary to
66   prevent staffline collisions if D is up (down).
67
68   If K is in CFG, then do nothing.
69 */
70
71 Dot_configuration
72 Dot_configuration::shifted (int k, Direction d) const
73 {
74   Dot_configuration new_cfg (*problem_);
75   int offset = 0;
76
77   if (d > 0)
78     {
79       for (Dot_configuration::const_iterator i (begin ());
80            i != end (); i++)
81         {
82           int p = i->first;
83           if (p == k)
84             {
85               if (Staff_symbol_referencer::on_line (i->second.dot_, p))
86                 p += d;
87               else
88                 p += 2* d;
89
90               offset = 2*d;
91
92               new_cfg[p] = i->second;
93             }
94           else
95             {
96               if (new_cfg.find (p) == new_cfg.end ())
97                 offset = 0;
98               new_cfg[p + offset] = i->second;
99             }
100         }
101     }
102   else
103     {
104       Dot_configuration::const_iterator i (end ());
105       do
106         {
107           i--;
108
109           int p = i->first;
110           if (p == k)
111             {
112               if (Staff_symbol_referencer::on_line (i->second.dot_, p))
113                 p += d;
114               else
115                 p += 2* d;
116
117               offset = 2*d;
118
119               new_cfg[p] = i->second;
120             }
121           else
122             {
123               if (new_cfg.find (p) == new_cfg.end ())
124                 offset = 0;
125
126               new_cfg[p + offset] = i->second;
127             }
128         }
129       while (i != begin ());
130     }
131
132   return new_cfg;
133 }
134
135 /*
136   Remove the collision in CFG either by shifting up or down, whichever
137   is best.
138 */
139 void
140 Dot_configuration::remove_collision (int p)
141 {
142   bool collide = find (p) != end ();
143
144   if (collide)
145     {
146       Dot_configuration cfg_up = shifted (p, UP);
147       Dot_configuration cfg_down = shifted (p, DOWN);
148
149       int b_up = cfg_up.badness ();
150       int b_down = cfg_down.badness ();
151
152       *this = (b_up < b_down) ? cfg_up : cfg_down;
153     }
154 }
155
156 Dot_configuration::Dot_configuration (Dot_formatting_problem const &problem)
157 {
158   problem_ = &problem;
159 }
160
161 Real
162 Dot_configuration::x_offset () const
163 {
164   Real off = 0.0;
165   for (Dot_configuration::const_iterator i (begin ());
166        i != end (); i++)
167     off = max (off, problem_->head_skyline_.height ((*i).first));
168
169   return off;
170 }