]> git.donarmstrong.com Git - lilypond.git/blob - lily/key-item.cc
c87f51ed7f226298f7528d8af356faff8aead0ce
[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--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7
8   keyplacement by Mats Bengtsson
9 */
10
11 #include "item.hh"
12 #include "key-item.hh"
13 #include "molecule.hh"
14 #include "paper-def.hh"
15 #include "font-interface.hh"
16 #include "staff-symbol-referencer.hh"
17 #include "lookup.hh"
18
19 /*
20   FIXME: too much hardcoding here.
21  */
22 const int FLAT_TOP_PITCH=2; /* fes,ges,as and bes typeset in lower octave */
23 const int SHARP_TOP_PITCH=4; /*  ais and bis typeset in lower octave */
24
25
26 /*
27   FIXME: key-item should just get a list of (position, acc), and leave
28   the thinking to other parties.
29
30   - TODO: put this in Scheme
31   
32   - lots of values trivially shared (key doesn't change very
33   often). Compute those once, and use that as cache for the rest.
34
35 */
36 int
37 alteration_pos  (SCM what, int alter, int c0p)
38 {
39   if (gh_pair_p (what))
40     return gh_scm2int (gh_car (what)) * 7 + gh_scm2int (gh_cdr (what)) + c0p;
41
42   int p = gh_scm2int (what);
43
44   // Find the c in the range -4 through 2
45   int from_bottom_pos = c0p + 4;
46   from_bottom_pos = from_bottom_pos%7;
47   from_bottom_pos = (from_bottom_pos + 7)%7; // Precaution to get positive.
48   int c0 = from_bottom_pos - 4;
49
50     
51   if ((alter <0 && ((p>FLAT_TOP_PITCH) || (p+c0>4)) && (p+c0>1)) 
52       ||
53       (alter >0 && ((p>SHARP_TOP_PITCH) || (p+c0>5)) && (p+c0>2))) 
54     {
55       p -= 7; /* Typeset below c_position */
56     }
57   /* Provide for the four cases in which there's a glitch 
58        it's a hack, but probably not worth  
59        the effort of finding a nicer solution.
60        --dl. */
61   if (c0==2 && alter >0 && p==3)
62     p -= 7;
63   if (c0==-3 && alter>0 && p==-1)
64     p += 7;
65   if (c0==-4 && alter<0 && p==-1)
66     p += 7;
67   if (c0==-2 && alter<0 && p==-3)
68     p += 7;
69     
70   return p + c0;
71 }
72
73 /*
74   TODO
75   - space the `natural' signs wider
76  */
77 MAKE_SCHEME_CALLBACK (Key_item,brew_molecule,1);
78 SCM
79 Key_item::brew_molecule (SCM smob)
80 {
81   Grob*me =unsmob_grob (smob);
82
83   Real inter = Staff_symbol_referencer::staff_space (me)/2.0;
84   
85   SCM newas = me->get_grob_property ("new-accidentals");  
86   Molecule mol;
87   /*
88     SCM lists are stacks, so we work from right to left, ending with
89     the cancellation signature.
90   */
91   int c0p = gh_scm2int (me->get_grob_property ("c0-position"));
92   for (SCM s = newas; gh_pair_p (s); s = gh_cdr (s))
93     {
94       SCM what = gh_caar (s);
95       int alter = gh_scm2int (gh_cdar (s));
96       int pos = alteration_pos (what, alter, c0p);
97       
98       Molecule m = Font_interface::get_default_font (me)->find_by_name ("accidentals-" + to_str (alter));
99       m.translate_axis (pos * inter, Y_AXIS);
100       mol.add_at_edge (X_AXIS, LEFT, m, 0);
101     }
102
103   Item *it = dynamic_cast<Item*> (me) ;
104   if (it->break_status_dir () != RIGHT)
105     {
106       SCM old = me->get_grob_property ("old-accidentals");
107       
108       /*
109         Add half a space between  cancellation and key sig.
110
111         As suggested by [Ross], p.148.
112        */
113       Interval x (0, inter);
114       Interval y (0,0);
115
116       mol.add_at_edge (X_AXIS, LEFT, Lookup::blank (Box (x,y)),0);
117
118       Molecule natural;
119       if (gh_pair_p (old))
120         natural=Font_interface::get_default_font (me)->find_by_name ("accidentals-0");
121       
122       for (; gh_pair_p (old); old = gh_cdr (old))
123         {
124           SCM found = scm_assoc (gh_caar (old), newas);
125           if (found == SCM_BOOL_F
126               || gh_cdr (found) != gh_cdar (old))
127             {
128               SCM what = gh_caar (old);
129               int alter = 0;
130               int pos = alteration_pos (what, alter, c0p);
131
132               Molecule m = natural;
133               m.translate_axis (pos* inter, Y_AXIS);
134
135               mol.add_at_edge (X_AXIS, LEFT, m, 0);
136             }
137         }
138     }
139
140   return mol.smobbed_copy ();
141 }
142
143
144
145
146
147 bool
148 Key_item::has_interface (Grob*m)
149 {
150   return m && m->has_interface (ly_symbol2scm ("key-signature-interface"));
151 }
152
153 void
154 Key_item::set_interface (Grob*m)
155 {
156   m->set_interface (ly_symbol2scm ("key-signature-interface"));
157 }