]> git.donarmstrong.com Git - lilypond.git/blob - lily/custos-engraver.cc
* lily/include/translator.icc (ADD_ACKNOWLEDGER): new macro.
[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 #include "pitch.hh"
17
18 #include "translator.icc"
19
20
21 /*
22  * This class implements an engraver for custos symbols.
23  *
24  * FIXME: note heads inside of ligatures (i.e. ligature heads) are
25  * sometimes not recognized by this engraver. --jr
26  */
27 class Custos_engraver : public Engraver
28 {
29 public:
30   TRANSLATOR_DECLARATIONS (Custos_engraver);
31   PRECOMPUTED_VIRTUAL void start_translation_timestep ();
32   DECLARE_ACKNOWLEDGER(bar);
33   DECLARE_ACKNOWLEDGER(note_head);
34   PRECOMPUTED_VIRTUAL void process_acknowledged ();
35   PRECOMPUTED_VIRTUAL void stop_translation_timestep ();
36   virtual void finalize ();
37
38 private:
39   Item *create_custos ();
40   bool custos_permitted_;
41   Link_array<Grob> custodes_;
42   Array<Pitch> pitches_;
43 };
44
45 Custos_engraver::Custos_engraver ()
46 {
47   custos_permitted_ = false;
48 }
49
50 void
51 Custos_engraver::stop_translation_timestep ()
52 {
53   /*
54     delay typeset until we're at the next moment, so we can silence custodes at the end of the piece.
55   */
56   pitches_.clear ();
57
58   custos_permitted_ = false;
59 }
60
61 void
62 Custos_engraver::start_translation_timestep ()
63 {
64   custodes_.clear ();
65 }
66
67 void
68 Custos_engraver::acknowledge_bar (Grob_info info)
69 {
70   custos_permitted_ = true;
71 }
72
73 void
74 Custos_engraver::acknowledge_note_head (Grob_info info)
75 {
76   Music *m = info.music_cause ();
77   if (m && m->is_mus_type ("note-event"))
78     {
79
80       /*
81         ideally, we'd do custos->set_parent (Y_AXIS, notehead),
82         but since the note head lives on the other system, we can't
83
84         So we copy the position from the note head pitch.  We
85         don't look at the staff-position, since we can't be sure
86         whether Clef_engraver already applied a vertical shift.
87       */
88       pitches_.push (*unsmob_pitch (m->get_property ("pitch")));
89     }
90 }
91
92 void
93 Custos_engraver::process_acknowledged ()
94 {
95   if (scm_is_string (get_property ("whichBar")))
96     custos_permitted_ = true;
97
98   if (custos_permitted_)
99     {
100       for (int i = pitches_.size (); i--;)
101         {
102           Item *c = create_custos ();
103
104           int p = pitches_[i].steps ();
105           SCM c0 = get_property ("middleCPosition");
106           if (scm_is_number (c0))
107             p += scm_to_int (c0);
108
109           c->set_property ("staff-position",
110                            scm_int2num (p));
111         }
112
113       pitches_.clear ();
114     }
115 }
116
117 Item *
118 Custos_engraver::create_custos ()
119 {
120   Item *custos = make_item ("Custos", SCM_EOL);
121
122   custodes_.push (custos);
123
124   return custos;
125 }
126
127 void
128 Custos_engraver::finalize ()
129 {
130   for (int i = custodes_.size (); i--;)
131     {
132       custodes_[i]->suicide ();
133     }
134   custodes_.clear ();
135 }
136
137
138 ADD_ACKNOWLEDGER(Custos_engraver,bar);
139 ADD_ACKNOWLEDGER(Custos_engraver,note_head);
140
141 ADD_TRANSLATOR (Custos_engraver,
142                 /* descr */ "",
143                 /* creats*/ "Custos",
144                 /* accepts */ "",
145                 /* acks  */ "",
146                 /* reads */ "",
147                 /* write */ "");