]> git.donarmstrong.com Git - lilypond.git/blob - lily/key-engraver.cc
Fix some bugs in the dynamic engraver and PostScript backend
[lilypond.git] / lily / key-engraver.cc
1 /*
2   key-engraver.cc -- implement Key_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "item.hh"
10 #include "bar-line.hh"
11 #include "staff-symbol-referencer.hh"
12 #include "context.hh"
13 #include "engraver.hh"
14 #include "protected-scm.hh"
15 #include "clef.hh"
16 #include "pitch.hh"
17
18 #include "translator.icc"
19
20 /*
21   TODO: The representation  of key sigs is all fucked.
22 */
23
24 /**
25    Make the key signature.
26 */
27 class Key_engraver : public Engraver
28 {
29   void create_key (bool);
30   void read_event (Music const *r);
31
32   Music *key_event_;
33   Item *item_;
34   Item *cancellation_;
35 public:
36   TRANSLATOR_DECLARATIONS (Key_engraver);
37
38 protected:
39   virtual void initialize ();
40   virtual void finalize ();
41   virtual bool try_music (Music *event);
42   void stop_translation_timestep ();
43   void process_music ();
44
45   DECLARE_ACKNOWLEDGER (clef);
46   DECLARE_ACKNOWLEDGER (bar_line);
47 };
48
49 void
50 Key_engraver::finalize ()
51 {
52 }
53
54 Key_engraver::Key_engraver ()
55 {
56   key_event_ = 0;
57   item_ = 0;
58   cancellation_ = 0;
59 }
60
61 void
62 Key_engraver::create_key (bool is_default)
63 {
64   if (!item_)
65     {
66       item_ = make_item ("KeySignature",
67                          key_event_ ? key_event_->self_scm () : SCM_EOL);
68
69       item_->set_property ("c0-position",
70                            get_property ("middleCPosition"));
71
72       SCM last = get_property ("lastKeySignature");
73       SCM key = get_property ("keySignature");
74
75       if ((to_boolean (get_property ("printKeyCancellation"))
76            || key == SCM_EOL)
77           && !scm_is_eq (last, key))
78         {
79           SCM restore = SCM_EOL;
80           SCM *tail = &restore;
81           for (SCM s = last; scm_is_pair (s); s = scm_cdr (s))
82             {
83               if (scm_assoc (scm_caar (s), key) == SCM_BOOL_F)
84                 {
85                   *tail = scm_acons (scm_caar (s),
86                                      scm_from_int (0), *tail);
87                   tail = SCM_CDRLOC (*tail);
88                 }
89             }
90
91           if (scm_is_pair (restore))
92             {
93               cancellation_ = make_item ("KeyCancellation",
94                                          key_event_
95                                          ? key_event_->self_scm () : SCM_EOL);
96           
97               cancellation_->set_property ("alteration-alist", restore);
98               cancellation_->set_property ("c0-position",
99                                            get_property ("middleCPosition"));
100             }
101         }
102       item_->set_property ("alteration-alist", key);
103     }
104
105   if (!is_default)
106     {
107       SCM visibility = get_property ("explicitKeySignatureVisibility");
108       item_->set_property ("break-visibility", visibility);
109       if (cancellation_)
110         cancellation_->set_property ("break-visibility", visibility);
111     }
112 }
113
114 bool
115 Key_engraver::try_music (Music *event)
116 {
117   if (event->is_mus_type ("key-change-event"))
118     {
119       /* do this only once, just to be on the safe side.  */
120       if (!key_event_)
121         {
122           key_event_ = event;
123           read_event (key_event_);
124         }
125       return true;
126     }
127   return false;
128 }
129
130 void
131 Key_engraver::acknowledge_clef (Grob_info info)
132 {
133   (void)info;
134   SCM c = get_property ("createKeyOnClefChange");
135   if (to_boolean (c))
136     create_key (false);
137 }
138
139 void
140 Key_engraver::acknowledge_bar_line (Grob_info info)
141 {
142   (void)info;
143   if (scm_is_pair (get_property ("keySignature")))
144     create_key (true);
145 }
146
147 void
148 Key_engraver::process_music ()
149 {
150   if (key_event_
151       || get_property ("lastKeySignature") != get_property ("keySignature"))
152     create_key (false);
153 }
154
155 void
156 Key_engraver::stop_translation_timestep ()
157 {
158   item_ = 0;
159   context ()->set_property ("lastKeySignature", get_property ("keySignature"));
160   cancellation_ = 0;
161   key_event_ = 0;
162 }
163
164 void
165 Key_engraver::read_event (Music const *r)
166 {
167   SCM p = r->get_property ("pitch-alist");
168   if (!scm_is_pair (p))
169     return;
170
171   SCM n = scm_list_copy (p);
172   SCM accs = SCM_EOL;
173   for (SCM s = get_property ("keyAlterationOrder");
174        scm_is_pair (s); s = scm_cdr (s))
175     {
176       if (scm_is_pair (scm_member (scm_car (s), n)))
177         {
178           accs = scm_cons (scm_car (s), accs);
179           n = scm_delete_x (scm_car (s), n);
180         }
181     }
182
183   for (SCM s = n; scm_is_pair (s); s = scm_cdr (s))
184     if (scm_to_int (scm_cdar (s)))
185       accs = scm_cons (scm_car (s), accs);
186
187   context ()->set_property ("keySignature", accs);
188   context ()->set_property ("tonic",
189                             r->get_property ("tonic"));
190 }
191
192 void
193 Key_engraver::initialize ()
194 {
195   context ()->set_property ("keySignature", SCM_EOL);
196   context ()->set_property ("lastKeySignature", SCM_EOL);
197
198   Pitch p (0, 0, 0);
199   context ()->set_property ("tonic", p.smobbed_copy ());
200 }
201
202 ADD_ACKNOWLEDGER (Key_engraver, clef);
203 ADD_ACKNOWLEDGER (Key_engraver, bar_line);
204
205 ADD_TRANSLATOR (Key_engraver,
206                 /* doc */ "",
207                 /* create */ "KeySignature",
208                 /* accept */ "key-change-event",
209                 
210                 /* read */
211                 "createKeyOnClefChange "
212                 "explicitKeySignatureVisibility "
213                 "keyAlterationOrder "
214                 "keySignature "
215                 "keySignature "
216                 "lastKeySignature "
217                 "printKeyCancellation "
218                 ,
219                 
220                 /* write */
221                 "keySignature "
222                 "lastKeySignature "
223                 "tonic ")