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