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