2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1998--2011 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 "separation-item.hh"
22 #include "accidental-placement.hh"
23 #include "axis-group-interface.hh"
25 #include "note-column.hh"
26 #include "note-head.hh"
27 #include "paper-column.hh"
28 #include "pointer-group-interface.hh"
29 #include "skyline-pair.hh"
34 Separation_item::add_item (Grob *s, Item *i)
37 Pointer_group_interface::add_grob (s, ly_symbol2scm ("elements"), i);
41 Separation_item::add_conditional_item (Grob *me, Grob *e)
43 Pointer_group_interface::add_grob (me, ly_symbol2scm ("conditional-elements"), e);
47 Separation_item::set_distance (Item *l, Item *r, Real padding)
49 Drul_array<Skyline_pair*> lines (Skyline_pair::unsmob (l->get_property ("horizontal-skylines")),
50 Skyline_pair::unsmob (r->get_property ("horizontal-skylines")));
51 Skyline right = conditional_skyline (r, l);
52 right.merge ((*lines[RIGHT])[LEFT]);
54 Real dist = padding + (*lines[LEFT])[RIGHT].distance (right);
59 rod.item_drul_ = Drul_array<Item*> (l, r);
65 return max (dist, 0.0);
69 Separation_item::is_empty (Grob *me)
71 Skyline_pair *sky = Skyline_pair::unsmob (me->get_property ("horizontal-skylines"));
72 return (!sky || sky->is_empty ());
76 Return the width of ME given that we are considering the object on
80 Separation_item::conditional_skyline (Grob *me, Grob *left)
82 vector<Box> bs = boxes (me, left);
83 Real horizon_padding = robust_scm2double (me->get_property ("skyline-vertical-padding"), 0.0);
84 return Skyline (bs, horizon_padding, Y_AXIS, LEFT);
88 MAKE_SCHEME_CALLBACK (Separation_item, calc_skylines,1);
90 Separation_item::calc_skylines (SCM smob)
92 Item *me = unsmob_item (smob);
93 vector<Box> bs = boxes (me, 0);
94 Real horizon_padding = robust_scm2double (me->get_property ("skyline-vertical-padding"), 0.0);
95 return Skyline_pair (bs, horizon_padding, Y_AXIS).smobbed_copy ();
98 /* if left is non-NULL, get the boxes corresponding to the
99 conditional-elements (conditioned on the grob LEFT). This
100 sounds more general than it is: conditional-elements are
101 always accidentals attached to a tied note.
104 Separation_item::boxes (Grob *me, Grob *left)
106 Item *item = dynamic_cast<Item *> (me);
108 int very_large = INT_MAX;
109 Paper_column *pc = item->get_column ();
111 extract_grob_set (me, left ? "conditional-elements" : "elements", read_only_elts);
115 elts = Accidental_placement::get_relevant_accidentals (read_only_elts, left);
118 elts = read_only_elts;
120 /* This is a special-case for NoteColumn: we want to include arpeggio in its
121 skyline (so spacing takes it into account) but we don't want to include it
122 in the NoteColumn's extent because some spanners (eg. Hairpin) bound themselves
123 on the NoteColumn and we don't want them to include arpeggios in their bounds.
125 if (Grob *a = Note_column::arpeggio (me)) {
130 Grob *ycommon = common_refpoint_of_array (elts, me, Y_AXIS);
132 for (vsize i = 0; i < elts.size (); i++)
134 Item *il = dynamic_cast<Item *> (elts[i]);
135 if (pc != il->get_column ())
138 /* ugh. We want to exclude groups of grobs (so that we insert each grob
139 individually into the skyline instead of adding a single box that
140 bounds all of them). However, we can't exclude an axis-group that
141 adds to its childrens' stencil. Currently, this is just TrillPitchGroup;
142 hence the check for note-head-interface. */
143 if (Axis_group_interface::has_interface (il)
144 && !Note_head::has_interface (il))
147 Interval y (il->pure_height (ycommon, 0, very_large));
148 Interval x (il->extent (pc, X_AXIS));
150 Interval extra_width = robust_scm2interval (elts[i]->get_property ("extra-spacing-width"),
151 Interval (-0.1, 0.1));
152 Interval extra_height = robust_scm2interval (elts[i]->get_property ("extra-spacing-height"),
153 Interval (0.0, 0.0));
155 x[LEFT] += extra_width[LEFT];
156 x[RIGHT] += extra_width[RIGHT];
157 y[DOWN] += extra_height[DOWN];
158 y[UP] += extra_height[UP];
160 if (!x.is_empty () && !y.is_empty ())
161 out.push_back (Box (x, y));
167 MAKE_SCHEME_CALLBACK (Separation_item, print, 1)
169 Separation_item::print (SCM smob)
174 Grob *me = unsmob_grob (smob);
176 if (Skyline_pair *s = Skyline_pair::unsmob (me->get_property ("horizontal-skylines")))
178 ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[LEFT].to_points (Y_AXIS)).in_color (255, 255, 0));
179 ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[RIGHT].to_points (Y_AXIS)).in_color (0, 255, 255));
181 return ret.smobbed_copy ();
184 ADD_INTERFACE (Separation_item,
185 "Item that computes widths to generate spacing rods.",
189 "conditional-elements "
192 "horizontal-skylines "
193 "skyline-vertical-padding "