]> git.donarmstrong.com Git - lilypond.git/blob - lily/rest-collision-engraver.cc
Nicer fix for 59.
[lilypond.git] / lily / rest-collision-engraver.cc
1 /*
2   rest-collision-engraver.cc -- implement Rest_collision_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include <set>
10
11 #include "duration.hh"
12 #include "engraver.hh"
13 #include "item.hh"
14 #include "moment.hh"
15 #include "note-column.hh"
16 #include "paper-column.hh"
17 #include "rest.hh"
18 #include "rest-collision.hh"
19 #include "rhythmic-head.hh"
20 #include "stream-event.hh"
21 #include "warn.hh"
22
23 class Rest_collision_engraver : public Engraver
24 {
25 protected:
26   Grob *rest_collision_;
27
28   void process_acknowledged ();
29   void stop_translation_timestep ();
30 public:
31   TRANSLATOR_DECLARATIONS (Rest_collision_engraver);
32 };
33
34 Rest_collision_engraver::Rest_collision_engraver ()
35 {
36   rest_collision_ = 0;
37 }
38
39 void
40 Rest_collision_engraver::process_acknowledged ()
41 {
42   vsize rest_count = 0;
43   set<Grob*> columns;
44   Moment now = now_mom ();
45
46   for (SCM s = get_property ("busyGrobs"); scm_is_pair (s); s = scm_cdr (s))
47     {
48       Grob *g = unsmob_grob (scm_cdar (s));
49       Moment *m = unsmob_moment (scm_caar (s));
50       if (!g || !m)
51         continue;
52
53       if (Rhythmic_head::has_interface (g) && (*m) > now)
54         {
55           Grob *column = g->get_parent (X_AXIS);
56
57           // Only include rests that start now. Include notes that started any time.
58           Paper_column *paper_column = dynamic_cast<Item*> (column)->get_column ();
59           if (!Rest::has_interface (g) || !paper_column || Paper_column::when_mom (paper_column) == now)
60             {
61               columns.insert (column);
62               rest_count += Note_column::has_rests (column);
63             }
64         }
65     }
66
67   if (!rest_collision_ && rest_count && columns.size () > 1)
68     {
69       rest_collision_ = make_item ("RestCollision", SCM_EOL);
70       for (set<Grob*>::iterator i = columns.begin (); i != columns.end (); ++i)
71         Rest_collision::add_column (rest_collision_, *i);
72     }
73 }
74
75 void
76 Rest_collision_engraver::stop_translation_timestep ()
77 {
78   rest_collision_ = 0;
79 }
80
81 #include "translator.icc"
82
83 ADD_TRANSLATOR (Rest_collision_engraver,
84                 /* doc */
85                 "Handle collisions of rests.",
86
87                 /* create */
88                 "RestCollision ",
89
90                 /* read */
91                 "busyGrobs ",
92
93                 /* write */
94                 ""
95                 );