]> git.donarmstrong.com Git - lilypond.git/blob - lily/clef-engraver.cc
patch::: 1.3.18.jcn1
[lilypond.git] / lily / clef-engraver.cc
1 /*
2   clef-engraver.cc -- implement Clef_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>,
7
8   Mats Bengtsson <matsb@s3.kth.se>
9 */
10
11 #include <ctype.h>
12 #include "staff-symbol-referencer.hh"
13 #include "bar.hh"
14 #include "clef-item.hh"
15 #include "debug.hh"
16 #include "command-request.hh"
17 #include "timing-translator.hh"
18 #include "note-head.hh"
19 #include "key-item.hh"
20 #include "local-key-item.hh"
21 #include "array.hh"
22 #include "engraver.hh"
23 #include "direction.hh"
24
25 /// where is c-0 in the staff?
26 class Clef_engraver : public  Engraver {
27   Clef_item * clef_p_;
28   Clef_change_req * clef_req_l_;
29   void create_clef();
30   bool set_type (String);
31 protected:
32   virtual void do_process_requests();
33   virtual void do_pre_move_processing();
34   virtual void do_creation_processing();
35   virtual void do_post_move_processing();
36   virtual bool do_try_music (Music*);
37   virtual void acknowledge_element (Score_element_info);
38 public:
39   VIRTUAL_COPY_CONS(Translator);
40   int c0_position_i_;
41   int clef_position_i_;
42                                 // junkme.
43   Direction octave_dir_;
44   SCM clef_glyph_;              // no need for protection. Always referenced somewhere else.
45    
46   Clef_engraver();
47 };
48
49
50 ADD_THIS_TRANSLATOR (Clef_engraver);
51
52 Clef_engraver::Clef_engraver()
53 {
54   clef_glyph_ = SCM_EOL;
55   clef_p_ = 0;
56   clef_req_l_ = 0;
57   c0_position_i_ = 0;
58   clef_position_i_ = 0;
59   octave_dir_ = CENTER;
60 }
61
62 bool
63 Clef_engraver::set_type (String s)
64 {
65   if (s.right_str(2) == "_8") // Down one octave
66     {
67       octave_dir_ = DOWN;
68       s = s.left_str(s.length_i() - 2);
69     }
70   else if (s.right_str(2) == "^8") // Up one octave
71     {
72       octave_dir_ = UP;
73       s = s.left_str(s.length_i() - 2);
74     }
75   else
76     octave_dir_ = CENTER;
77
78   SCM c = get_property ("supportedClefTypes",0);
79   SCM p = get_property ("clefPitches", 0);
80   
81   if (gh_list_p (c))
82     {
83       SCM found = scm_assoc (ly_str02scm (s.ch_C()), c);
84       if (found == SCM_BOOL_F)
85         return false;
86       
87       clef_glyph_  = gh_cadr (found);
88       SCM pos  = gh_caddr (found);
89
90       clef_position_i_ = gh_scm2int (pos);
91
92       found = scm_assoc (clef_glyph_, p);
93       if (found == SCM_BOOL_F)
94         return false;
95
96       c0_position_i_ = clef_position_i_ + gh_scm2int (gh_cdr (found));
97     }
98
99   c0_position_i_ -= (int) octave_dir_ * 7;
100   return true;
101 }
102
103
104 /** 
105   Generate a clef at the start of a measure. (when you see a Bar,
106   ie. a breakpoint) 
107   */
108 void
109 Clef_engraver::acknowledge_element (Score_element_info info)
110 {
111   if (dynamic_cast<Bar*>(info.elem_l_)
112       && gh_string_p (clef_glyph_))
113     create_clef();
114
115   /* ugh; should make Clef_referenced baseclass */
116   Item * it_l =dynamic_cast <Item *> (info.elem_l_);
117   if (it_l)
118     {
119       if (dynamic_cast<Note_head*>(it_l)
120           || dynamic_cast<Local_key_item*> (it_l)
121           )
122           
123         {
124           Staff_symbol_referencer_interface si (it_l);
125           si.set_position (int (si.position_f ()) + c0_position_i_);
126         }
127       else if (Key_item *k = dynamic_cast<Key_item*>(it_l))
128         {
129           k-> set_c_position (c0_position_i_);
130         }
131     } 
132 }
133
134 void
135 Clef_engraver::do_creation_processing()
136 {
137   SCM def = get_property ("defaultClef", 0);
138   if (gh_string_p (def))
139     {
140       set_type (ly_scm2string (def));
141       create_clef ();
142       clef_p_->set_elt_property ("non-default", SCM_BOOL_T);
143     }
144 }
145
146 bool
147 Clef_engraver::do_try_music (Music * r_l)
148 {
149   if (Clef_change_req *cl = dynamic_cast <Clef_change_req *> (r_l))
150     {
151       clef_req_l_ = cl;
152       if (!set_type (cl->clef_str_))
153         cl->error (_ ("unknown clef type"));
154
155       return true;
156     }
157   else
158     return false;
159
160 }
161
162 void
163 Clef_engraver::create_clef()
164 {
165   if (!clef_p_)
166     {
167       Clef_item *c= new Clef_item;
168       c->set_elt_property ("breakable", SCM_BOOL_T);
169       c->set_elt_property ("break-aligned", SCM_BOOL_T);
170       announce_element (Score_element_info (c, clef_req_l_));
171
172       Staff_symbol_referencer_interface si(c);
173       si.set_interface ();
174       
175       clef_p_ = c;
176     }
177   Staff_symbol_referencer_interface si(clef_p_);
178   clef_p_->set_elt_property ("glyph", clef_glyph_);
179   si.set_position (clef_position_i_);
180   if (octave_dir_)
181     {
182       clef_p_->set_elt_property ("octave-dir", gh_int2scm (octave_dir_));
183     }
184 }
185
186
187 void
188 Clef_engraver::do_process_requests()
189 {
190   if (clef_req_l_)
191     {
192       create_clef();
193       clef_p_->set_elt_property ("non-default", SCM_BOOL_T);
194     }
195 }
196
197 void
198 Clef_engraver::do_pre_move_processing()
199 {
200   if (clef_p_)
201     {
202       if(to_boolean (clef_p_->remove_elt_property("non-default")))
203          clef_p_->set_elt_property("visibility-lambda",
204                                    ly_eval_str ("all-visibility"));
205       
206       typeset_element (clef_p_);
207       clef_p_ =0;
208     }
209 }
210
211 void
212 Clef_engraver::do_post_move_processing()
213 {
214   clef_req_l_ = 0;
215 }
216