]> git.donarmstrong.com Git - lilypond.git/blob - lily/paper-column-engraver.cc
(parse_symbol_list): Bugfix.
[lilypond.git] / lily / paper-column-engraver.cc
1 /*
2   paper-column-engraver.cc -- implement Paper_column_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "paper-column-engraver.hh"
10 #include "system.hh"
11 #include "item.hh"
12 #include "paper-column.hh"
13 #include "staff-spacing.hh"
14 #include "note-spacing.hh"
15 #include "pointer-group-interface.hh"
16 #include "context.hh"
17 #include "axis-group-interface.hh"
18 #include "warn.hh"
19
20 #include "translator.icc"
21
22 Paper_column_engraver::Paper_column_engraver ()
23 {
24   command_column_ = 0;
25   musical_column_ = 0;
26   breaks_ = 0;
27   break_event_ = 0;
28   system_ = 0;
29   first_ = true;
30 }
31
32 void
33 Paper_column_engraver::finalize ()
34 {
35   if ((breaks_ % 8))
36     progress_indication ("[" + to_string (breaks_) + "]");
37
38   if (command_column_)
39     {
40       command_column_->set_property ("breakable", SCM_BOOL_T);
41       system_->set_bound (RIGHT, command_column_);
42     }
43 }
44
45 void
46 Paper_column_engraver::make_columns ()
47 {
48   /*
49     ugh.
50   */
51   Paper_column *p1 = make_paper_column ("NonMusicalPaperColumn");
52   Paper_column *p2 = make_paper_column ("PaperColumn");
53
54   SCM m = now_mom ().smobbed_copy ();
55   p1->set_property ("when", m);
56   p2->set_property ("when", m);
57
58   set_columns (p1, p2);
59 }
60
61 void
62 Paper_column_engraver::initialize ()
63 {
64   system_ = dynamic_cast<System *> (unsmob_grob (get_property ("rootSystem")));
65   make_columns ();
66
67   system_->set_bound (LEFT, command_column_);
68   command_column_->set_property ("breakable", SCM_BOOL_T);
69 }
70
71 void
72 Paper_column_engraver::acknowledge_item (Grob_info gi)
73 {
74   items_.push (gi.item ());
75 }
76
77 void
78 Paper_column_engraver::acknowledge_staff_spacing (Grob_info gi)
79 {
80   Pointer_group_interface::add_grob (command_column_,
81                                      ly_symbol2scm ("spacing-wishes"),
82                                      gi.grob ());
83 }
84 void
85 Paper_column_engraver::acknowledge_note_spacing (Grob_info gi)
86 {
87   Pointer_group_interface::add_grob (musical_column_,
88                                      ly_symbol2scm ("spacing-wishes"),
89                                      gi.grob ());
90 }
91
92 void
93 Paper_column_engraver::set_columns (Paper_column *new_command,
94                                     Paper_column *new_musical)
95 {
96   command_column_ = new_command;
97   musical_column_ = new_musical;
98   if (new_command)
99     {
100       context ()->set_property ("currentCommandColumn", new_command->self_scm ());
101     }
102
103   if (new_musical)
104     {
105       context ()->set_property ("currentMusicalColumn", new_musical->self_scm ());
106     }
107
108   system_->add_column (command_column_);
109   system_->add_column (musical_column_);
110 }
111
112 void
113 Paper_column_engraver::forbid_breaks ()
114 {
115   if (command_column_ && !first_)
116     command_column_->set_property ("breakable", SCM_EOL);
117 }
118
119 bool
120 Paper_column_engraver::try_music (Music *m)
121 {
122   break_event_ = m;
123
124   return true;
125 }
126
127 void
128 Paper_column_engraver::process_music ()
129 {
130   if (break_event_)
131     {
132       SCM pen = command_column_->get_property ("penalty");
133       Real total_penalty = scm_is_number (pen) ? scm_to_double (pen) : 0.0;
134
135       SCM mpen = break_event_->get_property ("penalty");
136       if (scm_is_number (mpen))
137         total_penalty += scm_to_double (mpen);
138
139       command_column_->set_property ("penalty", scm_from_double (total_penalty));
140
141       /* ugh.  arbitrary, hardcoded */
142       if (total_penalty > 10000.0)
143         forbid_breaks ();
144
145       SCM page_pen = command_column_->get_property ("page-penalty");
146       Real total_pp = scm_is_number (page_pen) ? scm_to_double (page_pen) : 0.0;
147       SCM mpage_pen = break_event_->get_property ("page-penalty");
148       if (scm_is_number (mpage_pen))
149         total_pp += scm_to_double (mpage_pen);
150
151       command_column_->set_property ("page-penalty", scm_from_double (total_pp));
152     }
153
154   bool start_of_measure = (last_moment_.main_part_ != now_mom ().main_part_
155                            && !measure_position (context ()).main_part_);
156
157   /*
158     We can't do this in start_translation_timestep(), since time sig
159     changes won't have happened by then.
160   */
161   if (start_of_measure)
162     {
163       Moment mlen = Moment (measure_length (context ()));
164       Grob *column = unsmob_grob (get_property ("currentCommandColumn"));
165       if (column)
166         column->set_property ("measure-length", mlen.smobbed_copy ());
167       else
168         programming_error ("No command column?");
169     }
170 }
171
172 void
173 Paper_column_engraver::stop_translation_timestep ()
174 {
175   for (int i = 0; i < items_.size (); i++)
176     {
177       Item *elem = items_[i];
178       if (!elem->get_parent (X_AXIS)
179           || !unsmob_grob (elem->get_object ("axis-group-parent-X")))
180         {
181           bool br = to_boolean (elem->get_property ("breakable"));
182           Axis_group_interface::add_element (br ? command_column_ : musical_column_, elem);
183         }
184     }
185   items_.clear ();
186
187   if (to_boolean (command_column_->get_property ("breakable")))
188     {
189       breaks_++;
190       if (! (breaks_%8))
191         progress_indication ("[" + to_string (breaks_) + "]");
192     }
193
194   first_ = false;
195   break_event_ = 0;
196 }
197
198 void
199 Paper_column_engraver::start_translation_timestep ()
200 {
201   /*
202     TODO: don't make columns when skipTypesetting is true.
203   */
204   if (!first_)
205     make_columns ();
206 }
207
208 ADD_ACKNOWLEDGER (Paper_column_engraver, item);
209 ADD_ACKNOWLEDGER (Paper_column_engraver, note_spacing);
210 ADD_ACKNOWLEDGER (Paper_column_engraver, staff_spacing);
211
212 ADD_TRANSLATOR (Paper_column_engraver,
213                 /* doc */ "Takes care of generating columns."
214                 "\n\n "
215                 "This engraver decides whether a column is breakable. The default is "
216                 "that a column is always breakable. However, when every Bar_engraver "
217                 "that does not have a barline at a certain point will call "
218                 "Score_engraver::forbid_breaks to stop linebreaks.  In practice, this "
219                 "means that you can make a breakpoint by creating a barline (assuming "
220                 "that there are no beams or notes that prevent a breakpoint.) ",
221                 /* create */ "PaperColumn NonMusicalPaperColumn",
222                 /* accept */ "break-event",
223                 /* read */ "",
224                 /* write */ "currentCommandColumn currentMusicalColumn");