]> git.donarmstrong.com Git - lilypond.git/blob - lily/key-item.cc
58a91cac61d2245c34b2f627fcf34ce757d611f3
[lilypond.git] / lily / key-item.cc
1 /*
2   key-item.cc -- implement Key_item
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1996, 1997--1998 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7
8   keyplacement by Mats Bengtsson
9 */
10
11 #include "key-item.hh"
12 #include "key.hh"
13 #include "debug.hh"
14 #include "molecule.hh"
15 #include "paper-def.hh"
16 #include "lookup.hh"
17
18 #include "key-engraver.hh"
19
20 const int FLAT_TOP_PITCH=2; /* fes,ges,as and bes typeset in lower octave */
21 const int SHARP_TOP_PITCH=4; /*  ais and bis typeset in lower octave */
22
23 Key_item::Key_item ()
24 {
25   breakable_b_ =true;
26   default_b_ = false;
27   set_c_position (0);
28 }
29
30 void
31 Key_item::read (Key_engraver const & key_grav_r)
32 {
33   multi_octave_b_ = key_grav_r.key_.multi_octave_b_;
34   const Array<Musical_pitch> &idx_arr = key_grav_r.accidental_idx_arr_; 
35   for (int i = 0; i < idx_arr.size(); i++) 
36     {
37       Musical_pitch m_l =idx_arr[i];
38       if (multi_octave_b_)
39          add (m_l);
40       else
41         add (m_l.notename_i_, m_l.accidental_i_);
42     }
43   const Array<Musical_pitch> &old_idx_arr = key_grav_r.old_accidental_idx_arr_; 
44   for (int i = 0 ; i< old_idx_arr.size(); i++) 
45     {
46       Musical_pitch m_l =old_idx_arr[i];
47       if (multi_octave_b_)
48          add_old (m_l);
49       else
50         add_old (m_l.notename_i_, m_l.accidental_i_);
51     }
52 }
53
54 void 
55 Key_item::set_c_position (int c0)
56 {
57   c0_position = c0;
58   // Find the c in the range -4 through 2
59   int from_bottom_pos = c0 + 4; 
60   from_bottom_pos = from_bottom_pos%7;
61   from_bottom_pos = (from_bottom_pos + 7)%7; // Precaution to get positive.
62   c_position  = from_bottom_pos - 4;
63 }
64
65
66 void
67 Key_item::add (int p, int a)
68 {
69   pitch.push (p);
70   acc.push (a);
71 }
72
73 void
74 Key_item::add (const Musical_pitch& pitch_r)
75 {
76   pitch.push (pitch_r.steps());
77   acc.push (pitch_r.accidental_i_);
78 }
79
80 void
81 Key_item::add_old (int p, int a)
82 {
83   old_pitch.push (p);
84   old_acc.push (a);
85 }
86
87 void
88 Key_item::add_old (const Musical_pitch& pitch_r)
89 {
90   old_pitch.push (pitch_r.steps());
91   old_acc.push (pitch_r.accidental_i_);
92 }
93
94 int
95 Key_item::calculate_position(int p, int a) const
96 {
97   if (multi_octave_b_) 
98     {
99       return p + c0_position;
100     }
101   else {
102     if ((a<0 && ((p>FLAT_TOP_PITCH) || (p+c_position>4)) && (p+c_position>1)) 
103         ||
104         (a>0 && ((p>SHARP_TOP_PITCH) || (p+c_position>5)) && (p+c_position>2))) 
105       {
106         p -= 7; /* Typeset below c_position */
107       }
108     return p + c_position;
109   }
110 }
111
112 /*
113   TODO space the `natural' signs wider
114  */
115 Molecule*
116 Key_item::brew_molecule_p() const
117 {
118   Molecule*output = new Molecule;
119   Real inter = paper()->internote_f ();
120   
121   int j;
122   if ((break_status_dir_ == LEFT || break_status_dir_ == CENTER)
123       || old_pitch.size ())
124     {
125       for (int i =0; i < old_pitch.size(); i++) 
126         {
127           for (j =0; (j < pitch.size()) && (old_pitch[i] != pitch[j]); j++) 
128             ;
129           
130           if (j == pitch.size()
131               || (old_pitch[i] == pitch[j] && old_acc[i] != acc[j]))
132             {
133               Atom a =lookup_l ()->accidental (0);
134               a.translate_axis (calculate_position(old_pitch[i], old_acc[i]) * inter, Y_AXIS);
135               Molecule m (a);
136               output->add_at_edge (X_AXIS, RIGHT, m);   
137             }
138         }
139
140       /*
141         Add half a space between  cancellation and key sig.
142
143         As suggested by [Ross], p.148.
144        */
145       Interval x(0, inter);
146       Interval y(0,0);
147
148       output->add_at_edge (X_AXIS, RIGHT, lookup_l()->fill (Box(x,y)));
149     }
150  
151   for (int i =0; i < pitch.size(); i++) 
152     {
153       Atom a =lookup_l ()->accidental (acc[i]);
154       a.translate_axis (calculate_position(pitch[i], acc[i]) * inter, Y_AXIS);
155       Molecule m (a);
156       output->add_at_edge (X_AXIS, RIGHT, m);   
157     }
158   if (pitch.size()) 
159     {
160       Molecule m (lookup_l ()->fill (Box (
161                                           Interval (0, paper()->note_width ()),
162                                           Interval (0,0))));
163       
164       output->add_at_edge (X_AXIS, RIGHT, m);
165     }
166   return output;
167 }
168
169 IMPLEMENT_IS_TYPE_B1(Key_item,Item);
170
171 void 
172 Key_item::do_pre_processing()
173 {
174   if (default_b_) 
175     {
176       transparent_b_ = (break_status_dir() != RIGHT);
177       set_empty (transparent_b_);
178     }
179 }