]> git.donarmstrong.com Git - lilypond.git/blob - lily/staff-symbol-referencer.cc
* lily/tie-column.cc (set_manual_tie_configuration): new function.
[lilypond.git] / lily / staff-symbol-referencer.cc
1 /*
2   staff-symbol-referencer.cc -- implement Staff_symbol_referencer
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1999--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "staff-symbol-referencer.hh"
10
11 #include <cmath>
12 using namespace std;
13
14 #include "staff-symbol.hh"
15 #include "output-def.hh"
16 #include "libc-extension.hh"
17
18 int
19 Staff_symbol_referencer::line_count (Grob *me)
20 {
21   Grob *st = get_staff_symbol (me);
22   return st ? Staff_symbol::line_count (st) : 0;
23 }
24
25 bool
26 Staff_symbol_referencer::on_staffline (Grob *me)
27 {
28   return on_staffline (me, (int) rint (get_position (me)));
29 }
30
31 /*
32   This does not take size into account.
33   maybe rename: on_virtual_staffline, on_staff_or_ledger_line?
34 */
35 bool
36 Staff_symbol_referencer::on_staffline (Grob *me, int pos)
37 {
38   int sz = line_count (me) - 1;
39   return ((pos + sz) % 2) == 0;
40 }
41
42 Grob *
43 Staff_symbol_referencer::get_staff_symbol (Grob *me)
44 {
45   if (Staff_symbol::has_interface (me))
46     return me;
47
48   SCM st = me->get_object ("staff-symbol");
49   return unsmob_grob (st);
50 }
51
52 Real
53 Staff_symbol_referencer::staff_space (Grob *me)
54 {
55   Grob *st = get_staff_symbol (me);
56   if (st)
57     return Staff_symbol::staff_space (st);
58   return 1.0;
59 }
60
61 Real
62 Staff_symbol_referencer::line_thickness (Grob *me)
63 {
64   Grob *st = get_staff_symbol (me);
65   if (st)
66     return Staff_symbol::get_line_thickness (st);
67   return me->get_layout ()->get_dimension (ly_symbol2scm ("linethickness"));
68 }
69
70 Real
71 Staff_symbol_referencer::get_position (Grob *me)
72 {
73   Real p = 0.0;
74   Grob *st = get_staff_symbol (me);
75   Grob *c = st ? me->common_refpoint (st, Y_AXIS) : 0;
76   if (st && c)
77     {
78       Real y = me->relative_coordinate (c, Y_AXIS)
79         - st->relative_coordinate (c, Y_AXIS);
80
81       p += 2.0 * y / Staff_symbol::staff_space (st);
82       return p;
83     }
84   else if (!st)
85     return me->relative_coordinate (me->get_parent (Y_AXIS), Y_AXIS) * 2;
86   return robust_scm2double (me->get_property ("staff-position"), p);
87 }
88
89 int
90 Staff_symbol_referencer::get_rounded_position (Grob *me)
91 {
92   return int (rint (get_position (me)));
93 }
94
95 LY_DEFINE (ly_grob_staff_position, "ly:grob-staff-position",
96            1, 0, 0, (SCM sg),
97            "Return the Y-position of @var{sg} relative to the staff.")
98 {
99   Grob *g = unsmob_grob (sg);
100
101   SCM_ASSERT_TYPE (g, sg, SCM_ARG1, __FUNCTION__, "grob");
102   Real pos = Staff_symbol_referencer::get_position (g);
103
104   if (fabs (rint (pos) -pos) < 1e-6) // ugh.
105     return scm_from_int ((int) my_round (pos));
106   else
107     return scm_from_double (pos);
108 }
109
110 /* should use offset callback!  */
111 MAKE_SCHEME_CALLBACK (Staff_symbol_referencer, callback, 2);
112 SCM
113 Staff_symbol_referencer::callback (SCM element_smob, SCM)
114 {
115   Grob *me = unsmob_grob (element_smob);
116
117   SCM pos = me->get_property ("staff-position");
118   Real off = 0.0;
119   if (scm_is_number (pos))
120     {
121       Real space = Staff_symbol_referencer::staff_space (me);
122       off = scm_to_double (pos) * space / 2.0;
123       me->set_property ("staff-position", scm_from_int (0));
124     }
125
126   return scm_from_double (off);
127 }
128
129 /*  This sets the position relative to the center of the staff symbol.
130
131 The function is hairy, because it can be called in two situations:
132
133 1. There is no staff yet; we must set staff-position
134
135 2. There is a staff, and perhaps someone even applied a
136 translate_axis (). Then we must compensate for the translation
137
138 In either case, we set a callback to be sure that our new position
139 will be extracted from staff-position */
140
141 void
142 Staff_symbol_referencer::set_position (Grob *me, Real p)
143 {
144   Grob *st = get_staff_symbol (me);
145   if (st && me->common_refpoint (st, Y_AXIS))
146     {
147       Real oldpos = get_position (me);
148       me->set_property ("staff-position", scm_from_double (p - oldpos));
149     }
150   else
151     me->set_property ("staff-position", scm_from_double (p));
152
153   me->add_offset_callback (Staff_symbol_referencer::callback_proc, Y_AXIS);
154 }
155
156 /* Half of the height, in staff space, i.e. 2.0 for a normal staff. */
157 Real
158 Staff_symbol_referencer::staff_radius (Grob *me)
159 {
160   return (line_count (me) - 1) / 2.0;
161 }
162
163 int
164 compare_position (Grob *const &a, Grob *const &b)
165 {
166   return sign (Staff_symbol_referencer::get_position ((Grob *)a)
167                - Staff_symbol_referencer::get_position ((Grob *) b));
168 }
169
170 ADD_INTERFACE (Staff_symbol_referencer, "staff-symbol-referencer-interface",
171                "An object whose Y position is meant relative to a staff "
172                "symbol. "
173                "These usually have @code{Staff_symbol_referencer::callback} "
174                "in their @code{Y-offset-callbacks}. ",
175                "staff-position");
176