Use scalar instead of embedded_scm for context mod overrides.
[lilypond/mpolesky.git] / lily / ambitus-engraver.cc
blobb1e89885aee9f5bae4bf7a6a21b91f606e99114a
1 /*
2 ambitus-engraver.cc -- implement Ambitus_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2002--2009 Juergen Reuter <reuter@ipd.uka.de>
8 Han-Wen Nienhuys <hanwen@xs4all.nl
9 */
11 #include "engraver.hh"
13 #include "accidental-placement.hh"
14 #include "axis-group-interface.hh"
15 #include "item.hh"
16 #include "note-head.hh"
17 #include "pitch-interval.hh"
18 #include "pointer-group-interface.hh"
19 #include "protected-scm.hh"
20 #include "side-position-interface.hh"
21 #include "separation-item.hh"
22 #include "staff-symbol-referencer.hh"
23 #include "stream-event.hh"
25 #include "translator.icc"
27 class Ambitus_engraver : public Engraver
29 public:
30 TRANSLATOR_DECLARATIONS (Ambitus_engraver);
31 protected:
32 DECLARE_ACKNOWLEDGER (note_head);
34 void process_music ();
35 void stop_translation_timestep ();
36 virtual void finalize ();
37 virtual void derived_mark () const;
39 private:
40 void create_ambitus ();
41 Item *ambitus_;
42 Item *group_;
43 Drul_array<Item *> heads_;
44 Drul_array<Item *> accidentals_;
45 Drul_array<Stream_event *> causes_;
46 Pitch_interval pitch_interval_;
47 bool is_typeset_;
48 int start_c0_;
49 SCM start_key_sig_;
52 void
53 Ambitus_engraver::derived_mark () const
55 scm_gc_mark (start_key_sig_);
58 void
59 Ambitus_engraver::create_ambitus ()
61 ambitus_ = make_item ("AmbitusLine", SCM_EOL);
62 group_ = make_item ("Ambitus", SCM_EOL);
63 Direction d = DOWN;
66 heads_[d] = make_item ("AmbitusNoteHead", SCM_EOL);
67 accidentals_[d] = make_item ("AmbitusAccidental", SCM_EOL);
68 accidentals_[d]->set_parent (heads_[d], Y_AXIS);
69 heads_[d]->set_object ("accidental-grob",
70 accidentals_[d]->self_scm ());
71 Axis_group_interface::add_element (group_, heads_[d]);
72 Axis_group_interface::add_element (group_, accidentals_[d]);
74 while (flip (&d) != DOWN);
76 ambitus_->set_parent (heads_[DOWN], X_AXIS);
77 Axis_group_interface::add_element (group_, ambitus_);
79 is_typeset_ = false;
82 Ambitus_engraver::Ambitus_engraver ()
84 ambitus_ = 0;
85 heads_.set (0, 0);
86 accidentals_.set (0, 0);
87 group_ = 0;
88 is_typeset_ = false;
89 start_key_sig_ = SCM_EOL;
92 void
93 Ambitus_engraver::process_music ()
96 * Ensure that ambitus is created in the very first timestep
98 if (!ambitus_)
99 create_ambitus ();
102 void
103 Ambitus_engraver::stop_translation_timestep ()
105 if (ambitus_ && !is_typeset_)
108 * Evaluate middleCPosition not until now, since otherwise we
109 * may then oversee a clef that is defined in a staff context if
110 * we are in a voice context; middleCPosition would then be
111 * assumed to be 0.
113 start_c0_ = robust_scm2int (get_property ("middleCPosition"), 0);
114 start_key_sig_ = get_property ("keySignature");
116 is_typeset_ = true;
120 void
121 Ambitus_engraver::acknowledge_note_head (Grob_info info)
123 Stream_event *nr = info.event_cause ();
124 if (nr && nr->in_event_class ("note-event"))
126 SCM p = nr->get_property ("pitch");
128 If the engraver is added to a percussion context,
129 filter out unpitched note heads.
131 if (!unsmob_pitch (p))
132 return;
133 Pitch pitch = *unsmob_pitch (p);
134 Drul_array<bool> expands = pitch_interval_.add_point (pitch);
135 if (expands[UP])
136 causes_[UP] = nr;
137 if (expands[DOWN])
138 causes_[DOWN] = nr;
142 void
143 Ambitus_engraver::finalize ()
145 if (ambitus_ && !pitch_interval_.is_empty ())
147 Grob *accidental_placement =
148 make_item ("AccidentalPlacement", accidentals_[DOWN]->self_scm ());
150 Direction d = DOWN;
153 Pitch p = pitch_interval_[d];
154 heads_[d]->set_property ("cause", causes_[d]->self_scm());
155 heads_[d]->set_property ("staff-position",
156 scm_from_int (start_c0_ + p.steps ()));
158 SCM handle = scm_assoc (scm_cons (scm_from_int (p.get_octave ()),
159 scm_from_int (p.get_notename ())),
160 start_key_sig_);
162 if (handle == SCM_BOOL_F)
163 handle = scm_assoc (scm_from_int (p.get_notename ()),
164 start_key_sig_);
166 Rational sig_alter = (handle != SCM_BOOL_F)
167 ? robust_scm2rational (scm_cdr (handle), Rational (0))
168 : Rational (0);
170 if (sig_alter == p.get_alteration ())
172 accidentals_[d]->suicide ();
173 heads_[d]->set_object ("accidental-grob", SCM_EOL);
175 else
176 accidentals_[d]->
177 set_property ("alteration",
178 ly_rational2scm (p.get_alteration ()));
179 Separation_item::add_conditional_item (heads_[d],
180 accidental_placement);
181 Accidental_placement::add_accidental (accidental_placement,
182 accidentals_[d]);
183 Pointer_group_interface::add_grob (ambitus_,
184 ly_symbol2scm ("note-heads"),
185 heads_[d]);
187 while (flip (&d) != DOWN);
189 Axis_group_interface::add_element (group_, accidental_placement);
191 else
193 Direction d = DOWN;
196 accidentals_[d]->suicide ();
197 heads_[d]->suicide ();
199 while (flip (&d) != DOWN);
201 ambitus_->suicide ();
205 ADD_ACKNOWLEDGER (Ambitus_engraver, note_head);
206 ADD_TRANSLATOR (Ambitus_engraver,
207 /* doc */
208 "Create an ambitus.",
210 /* create */
211 "AccidentalPlacement "
212 "Ambitus "
213 "AmbitusAccidental "
214 "AmbitusLine "
215 "AmbitusNoteHead ",
217 /* read */
218 "keySignature "
219 "middleCPosition ",
221 /* write */