]> git.donarmstrong.com Git - lilypond.git/blob - lily/accidental-placement.cc
''
[lilypond.git] / lily / accidental-placement.cc
1 /*   
2 accidental-placement.cc --  implement Accidental_placement
3
4 source file of the GNU LilyPond music typesetter
5
6 (c) 2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7
8  */
9
10
11 #include "item.hh"
12 #include "skyline.hh"
13 #include "music.hh"
14 #include "pitch.hh"
15 #include "warn.hh"
16 #include "accidental-placement.hh"
17
18
19 MAKE_SCHEME_CALLBACK(Accidental_placement,alignment_callback, 2);
20 SCM
21 Accidental_placement::alignment_callback(SCM s, SCM )
22 {
23   Grob * me =unsmob_grob (s);
24
25   Grob * par = me->get_parent (X_AXIS);
26   if (!to_boolean (par->get_grob_property ("done")))
27   {
28     par->set_grob_property ("done", SCM_BOOL_T);
29     position_accidentals (par);
30   }
31   
32
33   return gh_int2scm (0);
34 }
35
36 void
37 Accidental_placement::add_accidental (Grob* me, Grob* a)
38 {
39   a->set_parent (me, X_AXIS);
40   a->add_offset_callback (alignment_callback_proc, X_AXIS);
41   SCM cause = a->get_parent (Y_AXIS)->get_grob_property("cause");
42
43   Music *mcause =unsmob_music (cause); 
44   if (!mcause)
45     {
46       programming_error ("Note head has no music cause!");
47       return; 
48     }
49
50   Pitch *p= unsmob_pitch (mcause->get_mus_property ("pitch"));
51
52   int n = p->notename_i_;
53
54   SCM accs = me->get_grob_property ("accidentals");
55   SCM key = gh_int2scm (n);
56   SCM entry = scm_assq (key, accs);
57   if (entry == SCM_BOOL_F)
58     {
59       entry = SCM_EOL;
60     }
61   else
62     entry = gh_cdr (entry);
63
64   entry = gh_cons (a->self_scm (), entry);
65
66   accs = scm_assq_set_x (accs,  key, entry);
67
68   me->set_grob_property ("accidentals", accs);
69 }
70
71
72 struct Accidental_placement_entry
73 {
74   Array<Skyline_entry> left_skyline_;
75   Array<Skyline_entry> right_skyline_;
76   Interval vertical_extent_;
77   Array<Box> extents_;
78   Link_array<Grob> grobs_;
79   int notename_;
80 };
81
82 int ape_compare (Accidental_placement_entry *const &a,
83                  Accidental_placement_entry *const &b)
84 {
85   return sign (a->vertical_extent_.length () - b->vertical_extent_.length());
86 }
87
88 void
89 Accidental_placement::position_accidentals (Grob * me)
90 {
91   SCM accs = me->get_grob_property ("accidentals");
92
93   Link_array<Accidental_placement_entry> apes;
94   for (SCM s = accs; gh_pair_p (s); s =gh_cdr (s))
95     {
96       Accidental_placement_entry *ape = new Accidental_placement_entry;
97       ape->notename_ = gh_scm2int (gh_caar (s));
98       
99       for (SCM t = gh_cdar (s); gh_pair_p (t); t =gh_cdr (t))
100         ape->grobs_.push (unsmob_grob (gh_car (t)));
101
102       apes.push (ape);
103     }
104
105
106   Grob *commony =0 ;
107   for (int i= apes.size (); i--;)
108     for (int j = apes[i]->grobs_.size(); j--;)
109       {
110         Grob * a = apes[i]->grobs_[j];
111
112         if (commony)
113           commony =commony->common_refpoint (a, Y_AXIS);
114         else
115           commony =a;
116       }
117
118   for (int i= apes.size (); i--;)
119     {
120       Interval y ;
121       
122       for (int j = apes[i]->grobs_.size(); j--;)
123         {
124           Grob * a = apes[i]->grobs_[j];
125           Box b;
126           b[X_AXIS] = a->extent (me, X_AXIS);
127           b[Y_AXIS] = a->extent (commony, Y_AXIS);
128
129           y.unite (b[Y_AXIS]);
130           apes[i]->extents_.push (b);
131         }
132
133       apes[i]->vertical_extent_ = y;
134     }
135   
136   for (int i= apes.size (); i--;)
137     {
138       Accidental_placement_entry * ape = apes[i];
139       ape->left_skyline_ = extents_to_skyline (apes[i]->extents_, Y_AXIS, LEFT);
140       ape->right_skyline_ = extents_to_skyline (apes[i]->extents_, Y_AXIS, RIGHT);
141     }
142
143   apes.sort (&ape_compare);  
144
145   for (int i= apes.size ()-1; i-- > 0;)
146     {
147       Accidental_placement_entry *ape = apes[i];
148       Real here = 0.0;
149
150       Real d = skyline_meshing_distance (ape->right_skyline_, apes[i+1]->left_skyline_);
151
152       here += d;
153       for (int j  = ape->grobs_.size(); j--;)
154         {
155           ape->grobs_[j]->translate_axis (here, X_AXIS);
156         }
157     }
158
159   for (int i = apes.size(); i--;)
160     delete apes[i];
161 }
162
163 ADD_INTERFACE(Accidental_placement,
164               "accidental-placement-interface",
165               "Take care of complex accidental collisions.",
166               "accidentals done")