]> git.donarmstrong.com Git - lilypond.git/blob - lily/piano-pedal-engraver.cc
patch::: 1.3.43.jcn1
[lilypond.git] / lily / piano-pedal-engraver.cc
1 /*   
2   piano-pedal-engraver.cc --  implement Piano_pedal_engraver
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 2000 Jan Nieuwenhuizen <janneke@gnu.org>
7   
8  */
9
10 #include "engraver.hh"
11 #include "musical-request.hh"
12 #include "score-element.hh"
13 #include "item.hh"
14 #include "lookup.hh"
15 #include "lily-guile.hh"
16 #include "note-head.hh"
17 #include "stem.hh"
18 #include "side-position-interface.hh"
19 #include "staff-symbol-referencer.hh"
20
21
22 /*
23   TODO:
24     sostenuto
25     una-chorda / tre-corde
26  */
27
28
29 /*
30   Urg.
31   This is almost text
32   Problem is:
33     * we have no kerning
34     * symbols are at wrong place in font
35 */
36
37 class Sustain_pedal : public Item
38 {
39 public:
40   VIRTUAL_COPY_CONS (Score_element);
41
42 protected:
43   virtual Molecule do_brew_molecule () const;
44   virtual void after_line_breaking ();
45 };
46
47 void
48 Sustain_pedal::after_line_breaking ()
49 {
50   Side_position_interface i (this);
51   Direction d =  i.get_direction ();
52   i.set_direction (d);
53 }
54
55 Molecule
56 Sustain_pedal::do_brew_molecule () const
57 {
58   Molecule mol;
59   SCM glyph = get_elt_property ("glyph");
60   if (glyph == SCM_UNDEFINED)
61     return mol;
62   String text = ly_scm2string (glyph);
63
64   for (int i = 0; i < text.length_i (); i++)
65     {
66       // leuke koor dump door tiepo, snapnie helemaal:
67       //String idx = ("pedal-") + text[i];
68       // urg, Byte* ??
69       // braak: waarom vindt String het zo moeilijk om
70       // String + char te doen?
71       //String idx = "pedal-" + String (&text.byte_C ()[i], 1);
72       String idx = String ("pedal-") + String (&text.byte_C ()[i], 1);
73       Molecule m = lookup_l ()->afm_find (idx);
74       if (m.empty_b ())
75         continue;
76       Real kern = 0;
77       if (i)
78         {
79           SCM s = scm_eval (gh_list (ly_symbol2scm ("pedal-kerning"),
80                                      ly_str02scm (String (&text.byte_C ()[i - 1], 1).ch_C ()),
81                                      ly_str02scm (String (&text.byte_C ()[i], 1).ch_C ()),
82                                      SCM_UNDEFINED));
83           if (gh_number_p (s))
84             {
85               Staff_symbol_referencer_interface st (this);
86               Real staff_space = st.staff_space ();
87               kern = gh_scm2double (s) * staff_space;
88             }
89         }
90       mol.add_at_edge (X_AXIS, RIGHT, m, kern);
91     }
92     
93   return mol;
94 }
95
96 /**
97    engrave Piano pedals
98  */
99 class Piano_pedal_engraver : public Engraver
100 {
101 public:
102   VIRTUAL_COPY_CONS (Translator);
103   Piano_pedal_engraver ();
104
105 protected:
106   virtual bool do_try_music (Music*);
107   virtual void do_process_music ();
108   virtual void do_pre_move_processing ();
109   virtual void do_post_move_processing ();
110   virtual void acknowledge_element (Score_element_info);
111
112 private:
113   Span_req* sustain_start_req_l_;
114   Drul_array<Span_req*> sustain_req_l_drul_;
115   Sustain_pedal* sustain_p_;
116 };
117
118 ADD_THIS_TRANSLATOR(Piano_pedal_engraver);
119
120 Piano_pedal_engraver::Piano_pedal_engraver ()
121 {
122   sustain_p_ = 0;
123   sustain_req_l_drul_[START] = 0;
124   sustain_req_l_drul_[STOP] = 0;
125   sustain_start_req_l_ = 0;
126 }
127
128 /*
129   Urg: Code dup
130   I'm a script
131  */
132 void
133 Piano_pedal_engraver::acknowledge_element (Score_element_info i)
134 {
135   if (sustain_p_)
136     {
137       if (Note_head* n = dynamic_cast<Note_head*> (i.elem_l_))
138         {
139           Side_position_interface st (sustain_p_);
140           st.add_support (n);
141           if (st.get_axis( ) == X_AXIS
142               && !sustain_p_->parent_l (Y_AXIS))
143             sustain_p_->set_parent (n, Y_AXIS);
144         }
145       if (Stem* s = dynamic_cast<Stem*> (i.elem_l_))
146         {
147           Side_position_interface st (sustain_p_);
148           st.add_support (s);
149         }
150     }
151 }
152
153 bool
154 Piano_pedal_engraver::do_try_music (Music *m)
155 {
156   if (Span_req * s = dynamic_cast<Span_req*>(m))
157     {
158       if (s->span_type_str_ == "sustain")
159         {
160           sustain_req_l_drul_[s->span_dir_] = s;
161           return true;
162         }
163     }
164   return false;
165 }
166
167 void
168 Piano_pedal_engraver::do_process_music ()
169 {
170   SCM s = SCM_UNDEFINED;
171   if (sustain_req_l_drul_[STOP] && sustain_req_l_drul_[START])
172     {
173       if (!sustain_start_req_l_)
174         {
175           sustain_req_l_drul_[STOP]->warning (_ ("can't find start of piano_pedal"));
176         }
177       else
178         {
179           s = get_property ("stopStartSustain");
180           if (!gh_string_p (s))
181             s = ly_str02scm ("*Ped.");
182         }
183       sustain_start_req_l_ = sustain_req_l_drul_[START];
184     }
185   else if (sustain_req_l_drul_[STOP])
186     {
187       if (!sustain_start_req_l_)
188         {
189           sustain_req_l_drul_[STOP]->warning (_ ("can't find start of piano_pedal"));
190         }
191       else
192         {
193           s = get_property ("stopSustain");
194           if (!gh_string_p (s))
195             s = ly_str02scm ("*");
196         }
197       sustain_start_req_l_ = 0;
198     }
199   else if (sustain_req_l_drul_[START])
200     {
201       sustain_start_req_l_ = sustain_req_l_drul_[START];
202       s = get_property ("startSustain");
203       if (!gh_string_p (s))
204         s = ly_str02scm ("Ped.");
205     }
206   if (s != SCM_UNDEFINED)
207     {
208       sustain_p_ = new Sustain_pedal;
209       sustain_p_->set_elt_property ("glyph", s);
210
211
212       Side_position_interface si (sustain_p_);
213       si.set_axis (Y_AXIS);
214
215       /* Hmm,
216          If set to empty, it can't be centred
217          Howto centre non-fat text?
218          sustain_p_->set_empty (X_AXIS);
219       */
220       sustain_p_->set_elt_property ("self-alignment-X", gh_int2scm (0));
221       sustain_p_->add_offset_callback (Side_position_interface::aligned_on_self, X_AXIS);
222       sustain_p_->add_offset_callback (Side_position_interface::centered_on_parent, X_AXIS);
223       announce_element (Score_element_info (sustain_p_,
224                                             sustain_req_l_drul_[START]
225                                             ? sustain_req_l_drul_[START]
226                                             : sustain_req_l_drul_[STOP]));
227     }
228 }
229
230 void
231 Piano_pedal_engraver::do_pre_move_processing ()
232 {
233   if (sustain_p_)
234     {
235       side_position (sustain_p_).add_staff_support ();
236       typeset_element (sustain_p_);
237     }
238   sustain_p_ = 0;
239 }
240
241 void
242 Piano_pedal_engraver::do_post_move_processing ()
243 {
244   sustain_req_l_drul_[STOP] = 0;
245   sustain_req_l_drul_[START] = 0;
246 }