2 accidental-placement.cc -- implement Accidental_placement
4 source file of the GNU LilyPond music typesetter
6 (c) 2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
16 #include "accidental-placement.hh"
19 MAKE_SCHEME_CALLBACK(Accidental_placement,alignment_callback, 2);
21 Accidental_placement::alignment_callback(SCM s, SCM )
23 Grob * me =unsmob_grob (s);
25 Grob * par = me->get_parent (X_AXIS);
26 if (!to_boolean (par->get_grob_property ("done")))
28 par->set_grob_property ("done", SCM_BOOL_T);
29 position_accidentals (par);
33 return gh_int2scm (0);
37 Accidental_placement::add_accidental (Grob* me, Grob* a)
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");
43 Music *mcause =unsmob_music (cause);
46 programming_error ("Note head has no music cause!");
50 Pitch *p= unsmob_pitch (mcause->get_mus_property ("pitch"));
52 int n = p->notename_i_;
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)
62 entry = gh_cdr (entry);
64 entry = gh_cons (a->self_scm (), entry);
66 accs = scm_assq_set_x (accs, key, entry);
68 me->set_grob_property ("accidentals", accs);
72 struct Accidental_placement_entry
74 Array<Skyline_entry> left_skyline_;
75 Array<Skyline_entry> right_skyline_;
76 Interval vertical_extent_;
78 Link_array<Grob> grobs_;
82 int ape_compare (Accidental_placement_entry *const &a,
83 Accidental_placement_entry *const &b)
85 return sign (a->vertical_extent_.length () - b->vertical_extent_.length());
89 Accidental_placement::position_accidentals (Grob * me)
91 SCM accs = me->get_grob_property ("accidentals");
93 Link_array<Accidental_placement_entry> apes;
94 for (SCM s = accs; gh_pair_p (s); s =gh_cdr (s))
96 Accidental_placement_entry *ape = new Accidental_placement_entry;
97 ape->notename_ = gh_scm2int (gh_caar (s));
99 for (SCM t = gh_cdar (s); gh_pair_p (t); t =gh_cdr (t))
100 ape->grobs_.push (unsmob_grob (gh_car (t)));
107 for (int i= apes.size (); i--;)
108 for (int j = apes[i]->grobs_.size(); j--;)
110 Grob * a = apes[i]->grobs_[j];
113 commony =commony->common_refpoint (a, Y_AXIS);
118 for (int i= apes.size (); i--;)
122 for (int j = apes[i]->grobs_.size(); j--;)
124 Grob * a = apes[i]->grobs_[j];
126 b[X_AXIS] = a->extent (me, X_AXIS);
127 b[Y_AXIS] = a->extent (commony, Y_AXIS);
130 apes[i]->extents_.push (b);
133 apes[i]->vertical_extent_ = y;
136 for (int i= apes.size (); i--;)
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);
143 apes.sort (&ape_compare);
145 for (int i= apes.size ()-1; i-- > 0;)
147 Accidental_placement_entry *ape = apes[i];
150 Real d = skyline_meshing_distance (ape->right_skyline_, apes[i+1]->left_skyline_);
153 for (int j = ape->grobs_.size(); j--;)
155 ape->grobs_[j]->translate_axis (here, X_AXIS);
159 for (int i = apes.size(); i--;)
163 ADD_INTERFACE(Accidental_placement,
164 "accidental-placement-interface",
165 "Take care of complex accidental collisions.",