2 staff-side.cc -- implement Staff_side_element
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 #include <math.h> // ceil.
11 #include "side-position-interface.hh"
14 #include "dimensions.hh"
15 #include "staff-symbol-referencer.hh"
16 #include "group-interface.hh"
19 Side_position::add_support (Grob
*me
, Grob
*e
)
21 Pointer_group_interface::add_element (me
, "side-support-elements",e
);
27 Side_position::get_direction (Grob
*me
)
29 SCM d
= me
->get_grob_property ("direction");
30 if (isdir_b (d
) && to_dir (d
))
33 Direction relative_dir
= Direction (1);
34 SCM reldir
= me
->get_grob_property ("side-relative-direction"); // should use a lambda.
37 relative_dir
= to_dir (reldir
);
40 SCM other_elt
= me
->get_grob_property ("direction-source");
41 Grob
* e
= unsmob_grob(other_elt
);
44 return (Direction
)(relative_dir
* Side_position::get_direction (e
));
51 Callback that does the aligning. Puts the element next to the support
54 MAKE_SCHEME_CALLBACK(Side_position
,side_position
,2);
56 Side_position::side_position (SCM element_smob
, SCM axis
)
58 Grob
*me
= unsmob_grob (element_smob
);
59 Axis a
= (Axis
) gh_scm2int (axis
);
61 Grob
*common
= me
->parent_l (a
);
62 SCM support
= me
->get_grob_property ("side-support-elements");
63 for (SCM s
= support
; s
!= SCM_EOL
; s
= gh_cdr (s
))
65 Grob
* e
= unsmob_grob (gh_car (s
));
67 common
= common
->common_refpoint (e
, a
);
71 for (SCM s
= support
; s
!= SCM_EOL
; s
= gh_cdr (s
))
74 Grob
* e
= unsmob_grob ( gh_car (s
));
77 dim
.unite (e
->extent (common
, a
));
86 Direction dir
= Side_position::get_direction (me
);
88 Real off
= me
->parent_l (a
)->relative_coordinate (common
, a
);
89 SCM minimum
= me
->remove_grob_property ("minimum-space");
91 Real total_off
= dim
[dir
] + off
;
92 SCM padding
= me
->remove_grob_property ("padding");
93 if (gh_number_p (padding
))
95 total_off
+= gh_scm2double (padding
) * dir
;
97 if (gh_number_p (minimum
) && total_off
* dir
< gh_scm2double (minimum
))
99 total_off
= gh_scm2double (minimum
) * dir
;
101 if (fabs (total_off
) > 100 CM
)
102 programming_error ("Huh ? Improbable staff side dim.");
104 return gh_double2scm (total_off
);
108 callback that centers the element on itself
110 MAKE_SCHEME_CALLBACK(Side_position
,aligned_on_self
,2);
112 Side_position::aligned_on_self (SCM element_smob
, SCM axis
)
114 Grob
*me
= unsmob_grob (element_smob
);
115 Axis a
= (Axis
) gh_scm2int (axis
);
116 String
s ("self-alignment-");
118 s
+= (a
== X_AXIS
) ? "X" : "Y";
120 SCM
align (me
->get_grob_property (s
.ch_C()));
121 if (gh_number_p (align
))
123 Interval
ext(me
->extent (me
,a
));
127 programming_error ("I'm empty. Can't align on self");
128 return gh_double2scm (0.0);
132 return gh_double2scm (- ext
.linear_combination (gh_scm2double (align
)));
135 else if (unsmob_grob (align
))
137 return gh_double2scm (- unsmob_grob (align
)->relative_coordinate (me
, a
));
139 return gh_double2scm (0.0);
145 directed_round (Real f
, Direction d
)
154 Callback that quantises in staff-spaces, rounding in the direction
155 of the elements "direction" elt property.
157 Only rounds when we're inside the staff, as determined by
158 Staff_symbol_referencer::staff_radius() */
159 MAKE_SCHEME_CALLBACK(Side_position
,quantised_position
,2);
161 Side_position::quantised_position (SCM element_smob
, SCM
)
163 Grob
*me
= unsmob_grob (element_smob
);
166 Direction d
= Side_position::get_direction (me
);
168 if (Staff_symbol_referencer::has_interface (me
))
170 Real p
= Staff_symbol_referencer::position_f (me
);
171 Real rp
= directed_round (p
, d
);
172 Real rad
= Staff_symbol_referencer::staff_radius (me
) *2 ;
175 if (abs (ip
) < rad
&& Staff_symbol_referencer::on_staffline (me
,ip
))
181 return gh_double2scm ((rp
- p
) * Staff_symbol_referencer::staff_space (me
) / 2.0);
183 return gh_double2scm (0.0);
187 Position next to support, taking into account my own dimensions and padding.
189 MAKE_SCHEME_CALLBACK(Side_position
,aligned_side
,2);
191 Side_position::aligned_side (SCM element_smob
, SCM axis
)
193 Grob
*me
= unsmob_grob (element_smob
);
194 Axis a
= (Axis
) gh_scm2int (axis
);
196 Direction d
= Side_position::get_direction (me
);
197 Real o
= gh_scm2double (side_position (element_smob
,axis
));
199 Interval iv
= me
->extent (me
, a
);
205 SCM pad
= me
->get_grob_property ("padding");
206 if (gh_number_p (pad
))
207 o
+= d
*gh_scm2double (pad
) ;
209 return gh_double2scm (o
);
213 Position centered on parent.
215 MAKE_SCHEME_CALLBACK(Side_position
,centered_on_parent
,2);
217 Side_position::centered_on_parent (SCM element_smob
, SCM axis
)
219 Grob
*me
= unsmob_grob (element_smob
);
220 Axis a
= (Axis
) gh_scm2int (axis
);
221 Grob
*him
= me
->parent_l (a
);
223 return gh_double2scm (him
->extent (him
,a
).center ());
228 Side_position::add_staff_support (Grob
*me
)
230 Grob
* st
= Staff_symbol_referencer::staff_symbol_l (me
);
238 Side_position::set_axis (Grob
*me
, Axis a
)
240 me
->add_offset_callback (Side_position::aligned_side_proc
, a
);
245 // ugh. doesn't cactch all variants.
247 Side_position::get_axis (Grob
*me
)
249 if (me
->has_offset_callback_b (Side_position::aligned_side_proc
, X_AXIS
)
250 || me
->has_offset_callback_b (Side_position::aligned_side_proc
, X_AXIS
))
258 Side_position::set_direction (Grob
*me
, Direction d
)
260 me
->set_grob_property ("direction", gh_int2scm (d
));
264 Side_position::set_minimum_space (Grob
*me
, Real m
)
266 me
->set_grob_property ("minimum-space", gh_double2scm (m
));
270 Side_position::set_padding (Grob
*me
, Real p
)
272 me
->set_grob_property ("padding", gh_double2scm (p
));
276 Side_position::has_interface (Grob
*me
)
278 return me
->has_interface (ly_symbol2scm ("side-position-interface"));
282 Side_position::supported_b (Grob
*me
)
284 SCM s
= me
->get_grob_property ("side-support-elements");