]> git.donarmstrong.com Git - lilypond.git/blob - lily/custos-engraver.cc
Update.
[lilypond.git] / lily / custos-engraver.cc
1 /*
2   custos-engraver.cc -- implement Custos_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2000--2005 Juergen Reuter <reuter@ipd.uka.de>,
7   Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 */
9
10 #include "engraver.hh"
11 #include "bar-line.hh"
12 #include "item.hh"
13 #include "note-head.hh"
14 #include "staff-symbol-referencer.hh"
15 #include "warn.hh"
16
17 /*
18  * This class implements an engraver for custos symbols.
19  *
20  * FIXME: note heads inside of ligatures (i.e. ligature heads) are
21  * sometimes not recognized by this engraver. --jr
22  */
23 class Custos_engraver : public Engraver
24 {
25 public:
26   TRANSLATOR_DECLARATIONS (Custos_engraver);
27   virtual void start_translation_timestep ();
28   virtual void acknowledge_grob (Grob_info);
29   virtual void process_acknowledged_grobs ();
30   virtual void stop_translation_timestep ();
31   virtual void finalize ();
32
33 private:
34   Item *create_custos ();
35   bool custos_permitted;
36   Link_array<Grob> custodes_;
37   Array<Pitch> pitches_;
38 };
39
40 Custos_engraver::Custos_engraver ()
41 {
42   custos_permitted = false;
43 }
44
45 void
46 Custos_engraver::stop_translation_timestep ()
47 {
48   /*
49     delay typeset until we're at the next moment, so we can silence custodes at the end of the piece.
50   */
51   pitches_.clear ();
52
53   custos_permitted = false;
54 }
55
56 void
57 Custos_engraver::start_translation_timestep ()
58 {
59   custodes_.clear ();
60 }
61
62 void
63 Custos_engraver::acknowledge_grob (Grob_info info)
64 {
65   Item *item = dynamic_cast<Item *> (info.grob_);
66   if (item)
67     {
68       Music *m = info.music_cause ();
69       if (Bar_line::has_interface (info.grob_))
70         custos_permitted = true;
71       else if (Note_head::has_interface (info.grob_)
72                && m
73                && m->is_mus_type ("note-event"))
74         {
75
76           /*
77             ideally, we'd do custos->set_parent (Y_AXIS, notehead),
78             but since the note head lives on the other system, we can't
79
80             So we copy the position from the note head pitch.  We
81             don't look at the staff-position, since we can't be sure
82             whether Clef_engraver already applied a vertical shift.
83           */
84           pitches_.push (*unsmob_pitch (m->get_property ("pitch")));
85         }
86     }
87 }
88
89 void
90 Custos_engraver::process_acknowledged_grobs ()
91 {
92   if (scm_is_string (get_property ("whichBar")))
93     custos_permitted = true;
94
95   if (custos_permitted)
96     {
97       for (int i = pitches_.size (); i--;)
98         {
99           Item *c = create_custos ();
100
101           int p = pitches_[i].steps ();
102           SCM c0 = get_property ("middleCPosition");
103           if (scm_is_number (c0))
104             p += scm_to_int (c0);
105
106           c->set_property ("staff-position",
107                            scm_int2num (p));
108         }
109
110       pitches_.clear ();
111     }
112 }
113
114 Item *
115 Custos_engraver::create_custos ()
116 {
117   Item *custos = make_item ("Custos", SCM_EOL);
118
119   custodes_.push (custos);
120
121   return custos;
122 }
123
124 void
125 Custos_engraver::finalize ()
126 {
127   for (int i = custodes_.size (); i--;)
128     {
129       custodes_[i]->suicide ();
130     }
131   custodes_.clear ();
132 }
133
134 ADD_TRANSLATOR (Custos_engraver,
135                 /* descr */ "",
136                 /* creats*/ "Custos",
137                 /* accepts */ "",
138                 /* acks  */ "bar-line-interface note-head-interface",
139                 /* reads */ "",
140                 /* write */ "");