]> git.donarmstrong.com Git - lilypond.git/blob - lily/dynamic-align-engraver.cc
Docs-fr: fix PDF docs build
[lilypond.git] / lily / dynamic-align-engraver.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 2008--2010 Han-Wen Nienhuys <hanwen@lilypond.org>
5   
6
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.
11
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.
16
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/>.
19 */
20
21 #include <set>
22
23 #include "engraver.hh"
24
25 #include "axis-group-interface.hh"
26 #include "directional-element-interface.hh"
27 #include "item.hh"
28 #include "side-position-interface.hh"
29 #include "spanner.hh"
30 #include "stream-event.hh"
31
32 #include "translator.icc"
33
34 class Dynamic_align_engraver : public Engraver
35 {
36   TRANSLATOR_DECLARATIONS (Dynamic_align_engraver);
37   DECLARE_ACKNOWLEDGER (note_column);
38   DECLARE_ACKNOWLEDGER (dynamic);
39   DECLARE_END_ACKNOWLEDGER (dynamic);
40
41 protected:
42   virtual void stop_translation_timestep ();
43
44 private:
45   void create_line_spanner (Stream_event *cause);
46   Spanner* line_;
47
48   vector<Spanner*> ended_;
49   vector<Spanner*> started_;
50   vector<Grob*> scripts_;
51   vector<Grob*> support_;
52   
53   set<Spanner*> running_;
54 };
55
56 Dynamic_align_engraver::Dynamic_align_engraver ()
57 {
58   line_ = 0;
59 }
60
61 ADD_ACKNOWLEDGER (Dynamic_align_engraver, dynamic);
62 ADD_ACKNOWLEDGER (Dynamic_align_engraver, note_column);
63 ADD_END_ACKNOWLEDGER (Dynamic_align_engraver, dynamic);
64
65 void
66 Dynamic_align_engraver::create_line_spanner (Stream_event* event)
67 {
68   if (!line_)
69     line_ = make_spanner ("DynamicLineSpanner",
70                           event ? event->self_scm() : SCM_EOL);
71 }
72
73 void
74 Dynamic_align_engraver::acknowledge_end_dynamic (Grob_info info)
75 {
76   if (Spanner::has_interface(info.grob()))
77     ended_.push_back (info.spanner ());
78 }
79
80 void
81 Dynamic_align_engraver::acknowledge_note_column (Grob_info info)
82 {
83   support_.push_back (info.grob ());
84 }
85
86 void
87 Dynamic_align_engraver::acknowledge_dynamic (Grob_info info)
88 {
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 ());
93   else if (info.item())
94     scripts_.push_back (info.item());
95   else
96     info.grob ()->programming_error ("Unknown dynamic grob.");
97
98   Axis_group_interface::add_element (line_, info.grob ());
99
100   if (cause)
101     {
102       if (Direction d = to_dir (cause->get_property ("direction")))
103         set_grob_direction (line_, d);
104     }
105 }
106
107 void
108 Dynamic_align_engraver::stop_translation_timestep ()
109 {
110   for (vsize i = 0; i < started_.size(); i++)
111     running_.insert (started_[i]);
112   for (vsize i = 0; i < ended_.size(); i++)
113     {
114       Spanner *sp = ended_[i];
115
116       set<Spanner*>::iterator it  = running_.find (sp);
117       if (it != running_.end())
118         running_.erase (it);
119       else
120         started_[i]->programming_error ("Lost track of this dynamic spanner.");
121     }
122
123   bool end = line_ && running_.empty ();
124   Direction d = LEFT;
125   do
126     {
127       if (line_
128           && ((d == LEFT && !line_->get_bound (LEFT))
129               || (end && d == RIGHT && !line_->get_bound (RIGHT))))
130         {
131           vector<Spanner*> const &spanners =
132             (d == LEFT) ? started_ : ended_;
133           
134           Grob *bound = 0;
135           if (scripts_.size())
136             bound = scripts_[0];
137           else if (spanners.size())
138             bound = spanners[0]->get_bound (d);
139           else
140             {
141               programming_error ("Started DynamicLineSpanner but have no left bound.");
142               bound = unsmob_grob (get_property ("currentMusicalColumn"));
143             }
144
145           line_->set_bound (d, bound);
146         }
147     }
148   while (flip (&d) != LEFT);
149
150   for (vsize i = 0; line_ && i < support_.size (); i++)
151     Side_position_interface::add_support (line_, support_[i]);
152
153   if (end) 
154     line_ = 0;
155
156   ended_.clear ();
157   started_.clear ();
158   scripts_.clear ();
159   support_.clear ();
160 }
161
162
163 ADD_TRANSLATOR (Dynamic_align_engraver,
164                 /* doc */
165                 "Align hairpins and dynamic texts on a horizontal line",
166
167                 /* create */
168                 "DynamicLineSpanner ",
169
170                 /* read */
171                 "currentMusicalColumn ",
172
173                 /* write */
174                 ""
175                 );