]> git.donarmstrong.com Git - lilypond.git/blob - lily/key-item.cc
47526b042d17236d99f4de53a4cded2b85ae92ed
[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 (ly_car (what)) * 7 + gh_scm2int (ly_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 scm_style = me->get_grob_property ("style");
86   String style;
87   if (gh_symbol_p (scm_style))
88     {
89       style = ly_scm2string (scm_symbol_to_string (scm_style));
90     }
91   else
92     {
93       style = "";
94     }
95
96   SCM newas = me->get_grob_property ("new-accidentals");  
97   Molecule mol;
98
99   SCM c0s = me->get_grob_property ("c0-position");
100   int c0p=0;
101   if (gh_number_p (c0s))
102      c0p = gh_scm2int (c0s);
103
104   /*
105     SCM lists are stacks, so we work from right to left, ending with
106     the cancellation signature.
107   */
108
109   for (SCM s = newas; gh_pair_p (s); s = ly_cdr (s))
110     {
111       SCM what = ly_caar (s);
112       int alter = gh_scm2int (ly_cdar (s));
113       int pos = alteration_pos (what, alter, c0p);
114       
115       Molecule m = Font_interface::get_default_font (me)->
116           find_by_name (String ("accidentals-") + style + to_str (alter));
117       m.translate_axis (pos * inter, Y_AXIS);
118       mol.add_at_edge (X_AXIS, LEFT, m, 0);
119     }
120
121   Item *it = dynamic_cast<Item*> (me) ;
122   if (it->break_status_dir () != RIGHT)
123     {
124       SCM old = me->get_grob_property ("old-accidentals");
125       
126       /*
127         Add half a space between  cancellation and key sig.
128
129         As suggested by [Ross], p.148.
130        */
131       Interval x (0, inter);
132       Interval y (0,0);
133
134       mol.add_at_edge (X_AXIS, LEFT, Lookup::blank (Box (x,y)),0);
135
136       Molecule natural;
137       if (gh_pair_p (old))
138         natural=Font_interface::get_default_font (me)->
139             find_by_name (String ("accidentals-") + style + String ("0"));
140       
141       for (; gh_pair_p (old); old = ly_cdr (old))
142         {
143           SCM found = scm_assoc (ly_caar (old), newas);
144           if (found == SCM_BOOL_F
145               || ly_cdr (found) != ly_cdar (old))
146             {
147               SCM what = ly_caar (old);
148               int alter = 0;
149               int pos = alteration_pos (what, alter, c0p);
150
151               Molecule m = natural;
152               m.translate_axis (pos* inter, Y_AXIS);
153
154               mol.add_at_edge (X_AXIS, LEFT, m, 0);
155             }
156         }
157     }
158
159   return mol.smobbed_copy ();
160 }
161
162 bool
163 Key_item::has_interface (Grob*m)
164 {
165   return m && m->has_interface (ly_symbol2scm ("key-signature-interface"));
166 }
167
168 void
169 Key_item::set_interface (Grob*m)
170 {
171   m->set_interface (ly_symbol2scm ("key-signature-interface"));
172 }