2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2012 Mike Solomon <mike@mikesolomon.org>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
21 #include "fingering-column.hh"
22 #include "pointer-group-interface.hh"
23 #include "staff-symbol-referencer.hh"
25 #include "paper-column.hh"
29 MAKE_SCHEME_CALLBACK (Fingering_column, calc_positioning_done, 1);
31 Fingering_column::calc_positioning_done (SCM smob)
33 Grob *me = unsmob_grob (smob);
34 Real padding = robust_scm2double (me->get_property ("padding"), 0.0);
38 map<Grob *, bool> shifted;
40 Real ss = Staff_symbol_referencer::staff_space (me);
42 me->set_property ("positioning-done", SCM_BOOL_T);
44 extract_grob_set (me, "fingerings", const_fingerings);
46 if (const_fingerings.size () < 2)
48 me->programming_error ("This FingeringColumn should have never been created.");
52 // order the fingerings from bottom to top
53 vector<Grob *> fingerings;
54 for (vsize i = 0; i < const_fingerings.size (); i++)
55 fingerings.push_back (const_fingerings[i]);
57 vector_sort (fingerings, pure_position_less);
59 Grob *common[2] = {common_refpoint_of_array (fingerings, me, X_AXIS),
60 common_refpoint_of_array (fingerings, me, Y_AXIS)};
62 for (vsize i = 0; i < fingerings.size (); i++)
63 fingerings[i]->translate_axis (-fingerings[i]->extent (common[Y_AXIS], Y_AXIS).length () / 2, Y_AXIS);
65 for (vsize i = min (fingerings.size () - 1, fingerings.size () / 2 + 1); i >= 1; i--)
66 for (vsize j = i; j--;)
68 Interval ex_i = fingerings[i]->extent (common[X_AXIS], X_AXIS);
69 Interval ex_j = fingerings[j]->extent (common[X_AXIS], X_AXIS);
70 Interval ey_i = fingerings[i]->extent (common[Y_AXIS], Y_AXIS);
71 Interval ey_j = fingerings[j]->extent (common[Y_AXIS], Y_AXIS);
72 Real tval = min (0.0, (ey_i[DOWN] - ey_j[UP] - padding) / 2);
73 if (tval != 0.0 && !intersection (ex_i, ex_j).is_empty ())
75 if (shifted[fingerings[i]] || shifted[fingerings[j]])
76 fingerings[j]->translate_axis (tval * 2, Y_AXIS);
79 fingerings[i]->translate_axis (-tval, Y_AXIS);
80 fingerings[j]->translate_axis (tval, Y_AXIS);
82 shifted[fingerings[i]] = true;
83 shifted[fingerings[j]] = true;
87 for (vsize i = fingerings.size () / 2 - 1; i < fingerings.size () - 1; i++)
88 for (vsize j = i + 1; j < fingerings.size (); j++)
90 Interval ex_i = fingerings[i]->extent (common[X_AXIS], X_AXIS);
91 Interval ex_j = fingerings[j]->extent (common[X_AXIS], X_AXIS);
92 Interval ey_i = fingerings[i]->extent (common[Y_AXIS], Y_AXIS);
93 Interval ey_j = fingerings[j]->extent (common[Y_AXIS], Y_AXIS);
94 Real tval = max (0.0, (ey_i[UP] - ey_j[DOWN] + padding) / 2);
95 if (tval != 0.0 && !intersection (ex_i, ex_j).is_empty ())
97 if (shifted[fingerings[i]] || shifted[fingerings[j]])
98 fingerings[j]->translate_axis (tval * 2, Y_AXIS);
101 fingerings[i]->translate_axis (-tval, Y_AXIS);
102 fingerings[j]->translate_axis (tval, Y_AXIS);
104 shifted[fingerings[i]] = true;
105 shifted[fingerings[j]] = true;
114 Fingering_column::add_fingering (Grob *fc, Grob *f)
116 Pointer_group_interface::add_grob (fc, ly_symbol2scm ("fingerings"), f);
117 f->set_parent (fc, X_AXIS);
118 f->set_property ("Y-offset", Grob::x_parent_positioning_proc);
121 ADD_INTERFACE (Fingering_column,
122 "Makes sure that fingerings placed laterally"