2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1997--2010 Han-Wen Nienhuys <hanwen@xs4all.nl>
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/>.
20 #include "span-bar.hh"
22 #include "font-interface.hh"
23 #include "dimensions.hh"
24 #include "output-def.hh"
27 #include "axis-group-interface.hh"
28 #include "bar-line.hh"
30 #include "pointer-group-interface.hh"
33 Span_bar::add_bar (Grob
*me
, Grob
*b
)
35 Pointer_group_interface::add_grob (me
, ly_symbol2scm ("elements"), b
);
38 MAKE_SCHEME_CALLBACK (Span_bar
, print
, 1);
42 (1) Elements from 'me->get_object ("elements")' must be
43 ordered according to their y coordinates relative to their common
44 axis group parent. Otherwise, the computation goes mad.
46 (2) This method depends on bar_engraver not being removed from
47 staff context. If bar_engraver is removed, the size of the staff
48 lines is evaluated as 0, which results in a solid span bar line
49 with faulty y coordinate. */
51 /* This routine was originally by Juergen Reuter, but it was a on the
52 bulky side. Rewritten by Han-Wen. */
54 Span_bar::print (SCM smobbed_me
)
56 Grob
*me
= unsmob_grob (smobbed_me
);
57 extract_grob_set (me
, "elements", elements
);
58 Grob
*refp
= common_refpoint_of_array (elements
, me
, Y_AXIS
);
60 SCM glyph
= me
->get_property ("glyph-name");
62 /* glyph may not be a string, when ME is killed by Hara Kiri in
64 if (!scm_is_string (glyph
))
67 string glyph_string
= ly_scm2string (glyph
);
69 /* compose span_bar_mol */
70 vector
<Interval
> extents
;
71 vector
<bool> make_span_bar
;
73 for (vsize i
= elements
.size (); i
--;)
75 Grob
*bar
= elements
[i
];
76 Interval ext
= Bar_line::bar_y_extent (bar
, refp
);
80 extents
.push_back (ext
);
81 make_span_bar
.push_back (to_boolean (bar
->get_property ("allow-span-bar")));
88 vector_sort (extents
, Interval::left_less
);
91 for (vsize i
= 1; i
< extents
.size (); i
++)
93 Interval prev_extent
= extents
[i
- 1];
94 Interval ext
= extents
[i
];
95 if (!prev_extent
.is_empty ())
97 Interval
l (prev_extent
[UP
],
100 if (l
.is_empty () || !make_span_bar
[i
])
102 /* There is overlap between the bar lines. Do nothing. */
106 Stencil interbar
= Bar_line::compound_barline (model_bar
,
110 interbar
.translate_axis (l
.center (), Y_AXIS
);
111 span_bar
.add_stencil (interbar
);
117 span_bar
.translate_axis (- me
->relative_coordinate (refp
, Y_AXIS
),
120 return span_bar
.smobbed_copy ();
123 MAKE_SCHEME_CALLBACK (Span_bar
, width
, 1);
125 Span_bar::width (SCM smob
)
127 Grob
*me
= unsmob_grob (smob
);
128 SCM gn
= me
->get_property ("glyph-name");
130 return ly_interval2scm (Interval ());
132 string gl
= ly_scm2string (gn
);
137 Stencil m
= Bar_line::compound_barline (me
, gl
, 40 PT
, false);
139 return ly_interval2scm (m
.extent (X_AXIS
));
142 MAKE_SCHEME_CALLBACK (Span_bar
, before_line_breaking
, 1);
144 Span_bar::before_line_breaking (SCM smob
)
146 Grob
*me
= unsmob_grob (smob
);
147 extract_grob_set (me
, "elements", elements
);
148 if (elements
.empty ())
151 return SCM_UNSPECIFIED
;
154 MAKE_SCHEME_CALLBACK (Span_bar
, center_on_spanned_callback
, 1);
157 Span_bar::center_on_spanned_callback (SCM smob
)
159 Grob
*me
= unsmob_grob (smob
);
160 Interval
i (get_spanned_interval (me
));
162 /* Bar_line::print delivers a barline of y-extent (-h/2, h/2), so
163 we have to translate ourselves to be in the center of the
164 interval that we span. */
168 return scm_from_double (0.0);
171 return scm_from_double (i
.center ());
176 MAKE_SCHEME_CALLBACK(Span_bar
, calc_glyph_name
, 1);
178 Span_bar::calc_glyph_name (SCM smob
)
180 Grob
*me
= unsmob_grob (smob
);
181 extract_grob_set (me
, "elements", elements
);
183 for (vsize i
= elements
.size ();
184 i
-- && !scm_is_string (gl
);)
185 gl
= elements
[i
]->get_property ("glyph-name");
187 if (!scm_is_string (gl
))
190 return SCM_UNSPECIFIED
;
193 string type
= ly_scm2string (gl
);
194 if (type
== "|:" || type
== "||:")
196 else if (type
== ":|")
198 else if (type
== ":|:")
200 else if (type
== ":|.|:")
202 else if (type
== ":|.:")
204 else if (type
== "'")
207 return ly_string2scm (type
);
211 Span_bar::get_spanned_interval (Grob
*me
)
213 return ly_scm2interval (Axis_group_interface::generic_group_extent (me
, Y_AXIS
));
216 MAKE_SCHEME_CALLBACK (Span_bar
, calc_bar_size
, 1);
218 Span_bar::calc_bar_size (SCM smob
)
220 Grob
*me
= unsmob_grob (smob
);
221 Interval
iv (get_spanned_interval (me
));
224 /* This happens if the bars are hara-kiried from under us. */
226 return scm_from_double (-1);
228 return scm_from_double (iv
.length ());
231 ADD_INTERFACE (Span_bar
,
232 "A bar line that is spanned between other barlines. This"
233 " interface is used for bar lines that connect different"