]> git.donarmstrong.com Git - lilypond.git/blob - lily/ligature-bracket-engraver.cc
new file.
[lilypond.git] / lily / ligature-bracket-engraver.cc
1 /*   
2   ligature-bracket-engraver.cc -- implement Ligature__bracket_engraver
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 2002 Juergen Reuter <reuter@ipd.uka.de>
7   
8  */
9 #include "engraver.hh"
10 #include "musical-request.hh"
11 #include "warn.hh"
12 #include "drul-array.hh"
13 #include "item.hh"
14 #include "spanner.hh"
15 #include "score-engraver.hh"
16 #include "note-head.hh"
17 #include "stem.hh"
18 #include "rest.hh"
19
20 class Ligature_bracket_engraver : public Engraver
21 {
22   Drul_array<Span_req*> reqs_drul_;
23   
24   Spanner *finished_ligature_bracket_p_;
25   Spanner *ligature_bracket_p_;
26   Span_req *prev_start_req_;
27
28   // moment where ligature started.
29   Moment ligature_start_mom_;
30   Grob *last_bound;
31
32 protected:
33   virtual void stop_translation_timestep ();
34   virtual void start_translation_timestep ();
35   virtual void finalize ();
36
37   virtual void acknowledge_grob (Grob_info);
38   virtual bool try_music (Music*);
39   virtual void process_music ();
40
41 public:
42   TRANSLATOR_DECLARATIONS(Ligature_bracket_engraver);
43
44 private:
45   void typeset_ligature_bracket ();
46 };
47
48
49 Ligature_bracket_engraver::Ligature_bracket_engraver ()
50 {
51   ligature_bracket_p_ = 0;
52   finished_ligature_bracket_p_ = 0;
53   reqs_drul_[LEFT] = reqs_drul_[RIGHT] = 0;
54   prev_start_req_ = 0;
55   last_bound = 0;
56 }
57
58 bool
59 Ligature_bracket_engraver::try_music (Music *m)
60 {
61   if (Span_req *req_ = dynamic_cast<Span_req*> (m))
62     {
63       if (scm_equal_p (req_->get_mus_property ("span-type"),
64                        ly_str02scm ("abort")) == SCM_BOOL_T)
65         {
66           reqs_drul_[START] = 0;
67           reqs_drul_[STOP] = 0;
68           if (ligature_bracket_p_)
69             ligature_bracket_p_->suicide ();
70           ligature_bracket_p_ = 0;
71         }
72       else if (scm_equal_p (req_->get_mus_property ("span-type"),
73                             ly_str02scm ("ligature-bracket")) == SCM_BOOL_T)
74         {
75           Direction d = req_->get_span_dir ();
76           reqs_drul_[d] = req_;
77           return true;
78         }
79     }
80   return false;
81 }
82
83 void
84 Ligature_bracket_engraver::process_music ()
85 {
86   if (reqs_drul_[STOP])
87     {
88       if (!ligature_bracket_p_)
89         reqs_drul_[STOP]->origin ()->warning (_ ("can't find start of ligature"));
90       else
91         {
92           if (!last_bound)
93             {
94               reqs_drul_[STOP]->origin ()->warning (_ ("no right bound"));
95             }
96           else
97             {
98               ligature_bracket_p_->set_bound (RIGHT, last_bound);
99             }
100         }
101       prev_start_req_ = 0;
102       finished_ligature_bracket_p_ = ligature_bracket_p_;
103       ligature_bracket_p_ = 0;
104     }
105   last_bound = unsmob_grob (get_property ("currentMusicalColumn"));
106
107   if (ligature_bracket_p_)
108     {
109       // TODO: maybe forbid breaks only if not transcribing
110       top_engraver ()->forbid_breaks ();
111     }
112   if (reqs_drul_[START])
113     {
114       if (ligature_bracket_p_)
115         {
116           reqs_drul_[START]->origin ()->warning (_ ("already have a ligature"));
117           return;
118         }
119
120       prev_start_req_ = reqs_drul_[START];
121       ligature_bracket_p_ = new Spanner (get_property ("LigatureBracket"));
122
123       Grob *bound = unsmob_grob (get_property ("currentMusicalColumn"));
124       if (!bound)
125         {
126           reqs_drul_[START]->origin ()->warning (_ ("no left bound"));
127         }
128       else
129         {
130           ligature_bracket_p_->set_bound (LEFT, bound);
131         }
132
133       ligature_start_mom_ = now_mom ();
134       
135       announce_grob(ligature_bracket_p_, reqs_drul_[START]->self_scm());
136     }
137 }
138
139 void
140 Ligature_bracket_engraver::start_translation_timestep ()
141 {
142   reqs_drul_[START] = 0;
143   reqs_drul_[STOP] = 0;
144 }
145
146 void
147 Ligature_bracket_engraver::typeset_ligature_bracket ()
148 {
149   if (finished_ligature_bracket_p_)
150     {
151       typeset_grob (finished_ligature_bracket_p_);
152       finished_ligature_bracket_p_ = 0;
153     }
154 }
155
156 void
157 Ligature_bracket_engraver::stop_translation_timestep ()
158 {
159   typeset_ligature_bracket ();
160 }
161
162 void
163 Ligature_bracket_engraver::finalize ()
164 {
165   typeset_ligature_bracket ();
166   if (ligature_bracket_p_)
167     {
168       prev_start_req_->origin ()->warning (_ ("unterminated ligature"));
169       ligature_bracket_p_->suicide ();
170     }
171 }
172
173 void
174 Ligature_bracket_engraver::acknowledge_grob (Grob_info info)
175 {
176   if (ligature_bracket_p_)
177     {
178       if (Rest::has_interface (info.grob_l_))
179         {
180           reqs_drul_[START]->origin ()->warning (_ ("ligature may not contain rest; ignoring rest"));
181           prev_start_req_->origin ()->warning (_ ("ligature was started here"));
182           // TODO: maybe better should stop ligature here rather than
183           // ignoring the rest?
184         }
185     }
186 }
187
188 ENTER_DESCRIPTION(Ligature_bracket_engraver,
189 /* descr */       "Handles Ligature_requests by engraving Ligature brackets.",
190 /* creats*/       "LigatureBracket",
191 /* acks  */       "rest-interface",
192 /* reads */       "",
193 /* write */       "");