2 dynamic-align-engraver.cc -- implement Dynamic_align_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2008--2009 Han-Wen Nienhuys <hanwen@lilypond.org>
12 #include "engraver.hh"
14 #include "axis-group-interface.hh"
15 #include "directional-element-interface.hh"
17 #include "side-position-interface.hh"
19 #include "stream-event.hh"
21 #include "translator.icc"
23 class Dynamic_align_engraver
: public Engraver
25 TRANSLATOR_DECLARATIONS (Dynamic_align_engraver
);
26 DECLARE_ACKNOWLEDGER (note_column
);
27 DECLARE_ACKNOWLEDGER (dynamic
);
28 DECLARE_END_ACKNOWLEDGER (dynamic
);
31 virtual void stop_translation_timestep ();
34 void create_line_spanner (Stream_event
*cause
);
37 vector
<Spanner
*> ended_
;
38 vector
<Spanner
*> started_
;
39 vector
<Grob
*> scripts_
;
40 vector
<Grob
*> support_
;
42 set
<Spanner
*> running_
;
45 Dynamic_align_engraver::Dynamic_align_engraver ()
50 ADD_ACKNOWLEDGER (Dynamic_align_engraver
, dynamic
);
51 ADD_ACKNOWLEDGER (Dynamic_align_engraver
, note_column
);
52 ADD_END_ACKNOWLEDGER (Dynamic_align_engraver
, dynamic
);
55 Dynamic_align_engraver::create_line_spanner (Stream_event
* event
)
58 line_
= make_spanner ("DynamicLineSpanner",
59 event
? event
->self_scm() : SCM_EOL
);
63 Dynamic_align_engraver::acknowledge_end_dynamic (Grob_info info
)
65 if (Spanner::has_interface(info
.grob()))
66 ended_
.push_back (info
.spanner ());
70 Dynamic_align_engraver::acknowledge_note_column (Grob_info info
)
72 support_
.push_back (info
.grob ());
76 Dynamic_align_engraver::acknowledge_dynamic (Grob_info info
)
78 Stream_event
*cause
= info
.event_cause ();
79 create_line_spanner (cause
);
80 if (Spanner::has_interface(info
.grob()))
81 started_
.push_back (info
.spanner ());
83 scripts_
.push_back (info
.item());
85 info
.grob ()->programming_error ("Unknown dynamic grob.");
87 Axis_group_interface::add_element (line_
, info
.grob ());
91 if (Direction d
= to_dir (cause
->get_property ("direction")))
92 set_grob_direction (line_
, d
);
97 Dynamic_align_engraver::stop_translation_timestep ()
99 for (vsize i
= 0; i
< started_
.size(); i
++)
100 running_
.insert (started_
[i
]);
101 for (vsize i
= 0; i
< ended_
.size(); i
++)
103 Spanner
*sp
= ended_
[i
];
105 set
<Spanner
*>::iterator it
= running_
.find (sp
);
106 if (it
!= running_
.end())
109 started_
[i
]->programming_error ("Lost track of this dynamic spanner.");
112 bool end
= line_
&& running_
.empty ();
117 && ((d
== LEFT
&& !line_
->get_bound (LEFT
))
118 || (end
&& d
== RIGHT
&& !line_
->get_bound (RIGHT
))))
120 vector
<Spanner
*> const &spanners
=
121 (d
== LEFT
) ? started_
: ended_
;
126 else if (spanners
.size())
127 bound
= spanners
[0]->get_bound (d
);
130 programming_error ("Started DynamicLineSpanner but have no left bound.");
131 bound
= unsmob_grob (get_property ("currentMusicalColumn"));
134 line_
->set_bound (d
, bound
);
137 while (flip (&d
) != LEFT
);
139 for (vsize i
= 0; line_
&& i
< support_
.size (); i
++)
140 Side_position_interface::add_support (line_
, support_
[i
]);
152 ADD_TRANSLATOR (Dynamic_align_engraver
,
154 "Align hairpins and dynamic texts on a horizontal line",
157 "DynamicLineSpanner ",
160 "currentMusicalColumn ",