]> git.donarmstrong.com Git - lilypond.git/blob - lily/custos-engraver.cc
* flower
[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
111       pitches_.clear ();
112     }
113 }
114
115 Item *
116 Custos_engraver::create_custos ()
117 {
118   Item *custos = make_item ("Custos", SCM_EOL);
119
120   custodes_.push (custos);
121
122   return custos;
123 }
124
125 void
126 Custos_engraver::finalize ()
127 {
128   for (int i = custodes_.size (); i--;)
129     {
130       custodes_[i]->suicide ();
131     }
132   custodes_.clear ();
133 }
134
135 ADD_TRANSLATOR (Custos_engraver,
136                 /* descr */ "",
137                 /* creats*/ "Custos",
138                 /* accepts */ "",
139                 /* acks  */ "bar-line-interface note-head-interface",
140                 /* reads */ "",
141                 /* write */ "");