2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2008--2010 Han-Wen Nienhuys <hanwen@lilypond.org>
7 LilyPond is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 LilyPond is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
23 #include "engraver.hh"
25 #include "axis-group-interface.hh"
26 #include "directional-element-interface.hh"
28 #include "side-position-interface.hh"
30 #include "stream-event.hh"
32 #include "translator.icc"
34 class Dynamic_align_engraver
: public Engraver
36 TRANSLATOR_DECLARATIONS (Dynamic_align_engraver
);
37 DECLARE_ACKNOWLEDGER (note_column
);
38 DECLARE_ACKNOWLEDGER (dynamic
);
39 DECLARE_END_ACKNOWLEDGER (dynamic
);
42 virtual void stop_translation_timestep ();
45 void create_line_spanner (Stream_event
*cause
);
48 vector
<Spanner
*> ended_
;
49 vector
<Spanner
*> started_
;
50 vector
<Grob
*> scripts_
;
51 vector
<Grob
*> support_
;
53 set
<Spanner
*> running_
;
56 Dynamic_align_engraver::Dynamic_align_engraver ()
61 ADD_ACKNOWLEDGER (Dynamic_align_engraver
, dynamic
);
62 ADD_ACKNOWLEDGER (Dynamic_align_engraver
, note_column
);
63 ADD_END_ACKNOWLEDGER (Dynamic_align_engraver
, dynamic
);
66 Dynamic_align_engraver::create_line_spanner (Stream_event
* event
)
69 line_
= make_spanner ("DynamicLineSpanner",
70 event
? event
->self_scm() : SCM_EOL
);
74 Dynamic_align_engraver::acknowledge_end_dynamic (Grob_info info
)
76 if (Spanner::has_interface(info
.grob()))
77 ended_
.push_back (info
.spanner ());
81 Dynamic_align_engraver::acknowledge_note_column (Grob_info info
)
83 support_
.push_back (info
.grob ());
87 Dynamic_align_engraver::acknowledge_dynamic (Grob_info info
)
89 Stream_event
*cause
= info
.event_cause ();
90 create_line_spanner (cause
);
91 if (Spanner::has_interface(info
.grob()))
92 started_
.push_back (info
.spanner ());
94 scripts_
.push_back (info
.item());
96 info
.grob ()->programming_error ("Unknown dynamic grob.");
98 Axis_group_interface::add_element (line_
, info
.grob ());
102 if (Direction d
= to_dir (cause
->get_property ("direction")))
103 set_grob_direction (line_
, d
);
108 Dynamic_align_engraver::stop_translation_timestep ()
110 for (vsize i
= 0; i
< started_
.size(); i
++)
111 running_
.insert (started_
[i
]);
112 for (vsize i
= 0; i
< ended_
.size(); i
++)
114 Spanner
*sp
= ended_
[i
];
116 set
<Spanner
*>::iterator it
= running_
.find (sp
);
117 if (it
!= running_
.end())
120 started_
[i
]->programming_error ("Lost track of this dynamic spanner.");
123 bool end
= line_
&& running_
.empty ();
128 && ((d
== LEFT
&& !line_
->get_bound (LEFT
))
129 || (end
&& d
== RIGHT
&& !line_
->get_bound (RIGHT
))))
131 vector
<Spanner
*> const &spanners
=
132 (d
== LEFT
) ? started_
: ended_
;
137 else if (spanners
.size())
138 bound
= spanners
[0]->get_bound (d
);
141 programming_error ("Started DynamicLineSpanner but have no left bound.");
142 bound
= unsmob_grob (get_property ("currentMusicalColumn"));
145 line_
->set_bound (d
, bound
);
148 while (flip (&d
) != LEFT
);
150 for (vsize i
= 0; line_
&& i
< support_
.size (); i
++)
151 Side_position_interface::add_support (line_
, support_
[i
]);
163 ADD_TRANSLATOR (Dynamic_align_engraver
,
165 "Align hairpins and dynamic texts on a horizontal line",
168 "DynamicLineSpanner ",
171 "currentMusicalColumn ",