]> git.donarmstrong.com Git - lilypond.git/blob - lily/paper-column-engraver.cc
Nitpick run.
[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     context ()->set_property ("currentCommandColumn", new_command->self_scm ());
100
101   if (new_musical)
102     context ()->set_property ("currentMusicalColumn", new_musical->self_scm ());
103
104   system_->add_column (command_column_);
105   system_->add_column (musical_column_);
106 }
107
108 void
109 Paper_column_engraver::forbid_breaks ()
110 {
111   if (command_column_ && !first_)
112     command_column_->set_property ("breakable", SCM_EOL);
113 }
114
115 bool
116 Paper_column_engraver::try_music (Music *m)
117 {
118   break_event_ = m;
119
120   return true;
121 }
122
123 void
124 Paper_column_engraver::process_music ()
125 {
126   if (break_event_)
127     {
128       SCM pen = command_column_->get_property ("penalty");
129       Real total_penalty = scm_is_number (pen) ? scm_to_double (pen) : 0.0;
130
131       SCM mpen = break_event_->get_property ("penalty");
132       if (scm_is_number (mpen))
133         total_penalty += scm_to_double (mpen);
134
135       command_column_->set_property ("penalty", scm_from_double (total_penalty));
136
137       /* ugh.  arbitrary, hardcoded */
138       if (total_penalty > 10000.0)
139         forbid_breaks ();
140
141       SCM page_pen = command_column_->get_property ("page-penalty");
142       Real total_pp = scm_is_number (page_pen) ? scm_to_double (page_pen) : 0.0;
143       SCM mpage_pen = break_event_->get_property ("page-penalty");
144       if (scm_is_number (mpage_pen))
145         total_pp += scm_to_double (mpage_pen);
146
147       command_column_->set_property ("page-penalty", scm_from_double (total_pp));
148     }
149
150   bool start_of_measure = (last_moment_.main_part_ != now_mom ().main_part_
151                            && !measure_position (context ()).main_part_);
152
153   /*
154     We can't do this in start_translation_timestep(), since time sig
155     changes won't have happened by then.
156   */
157   if (start_of_measure)
158     {
159       Moment mlen = Moment (measure_length (context ()));
160       Grob *column = unsmob_grob (get_property ("currentCommandColumn"));
161       if (column)
162         column->set_property ("measure-length", mlen.smobbed_copy ());
163       else
164         programming_error ("No command column?");
165     }
166 }
167
168 void
169 Paper_column_engraver::stop_translation_timestep ()
170 {
171   for (int i = 0; i < items_.size (); i++)
172     {
173       Item *elem = items_[i];
174       if (!elem->get_parent (X_AXIS)
175           || !unsmob_grob (elem->get_object ("axis-group-parent-X")))
176         {
177           bool br = to_boolean (elem->get_property ("breakable"));
178           Axis_group_interface::add_element (br ? command_column_ : musical_column_, elem);
179         }
180     }
181   items_.clear ();
182
183   if (to_boolean (command_column_->get_property ("breakable")))
184     {
185       breaks_++;
186       if (! (breaks_%8))
187         progress_indication ("[" + to_string (breaks_) + "]");
188     }
189
190   first_ = false;
191   break_event_ = 0;
192 }
193
194 void
195 Paper_column_engraver::start_translation_timestep ()
196 {
197   /*
198     TODO: don't make columns when skipTypesetting is true.
199   */
200   if (!first_)
201     make_columns ();
202 }
203
204 ADD_ACKNOWLEDGER (Paper_column_engraver, item);
205 ADD_ACKNOWLEDGER (Paper_column_engraver, note_spacing);
206 ADD_ACKNOWLEDGER (Paper_column_engraver, staff_spacing);
207
208 ADD_TRANSLATOR (Paper_column_engraver,
209                 /* doc */ "Takes care of generating columns."
210                 "\n\n "
211                 "This engraver decides whether a column is breakable. The default is "
212                 "that a column is always breakable. However, when every Bar_engraver "
213                 "that does not have a barline at a certain point will call "
214                 "Score_engraver::forbid_breaks to stop linebreaks.  In practice, this "
215                 "means that you can make a breakpoint by creating a barline (assuming "
216                 "that there are no beams or notes that prevent a breakpoint.) ",
217                 /* create */ "PaperColumn NonMusicalPaperColumn",
218                 /* accept */ "break-event",
219                 /* read */ "",
220                 /* write */ "currentCommandColumn currentMusicalColumn");