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);
87 MAKE_SCHEME_CALLBACK (Separation_item, calc_skylines, 1);
89 Separation_item::calc_skylines (SCM smob)
91 Item *me = unsmob_item (smob);
92 vector<Box> bs = boxes (me, 0);
93 Real horizon_padding = robust_scm2double (me->get_property ("skyline-vertical-padding"), 0.0);
94 return Skyline_pair (bs, horizon_padding, Y_AXIS).smobbed_copy ();
97 /* if left is non-NULL, get the boxes corresponding to the
98 conditional-elements (conditioned on the grob LEFT). This
99 sounds more general than it is: conditional-elements are
100 always accidentals attached to a tied note.
103 Separation_item::boxes (Grob *me, Grob *left)
105 Item *item = dynamic_cast<Item *> (me);
107 int very_large = INT_MAX;
108 Paper_column *pc = item->get_column ();
110 extract_grob_set (me, left ? "conditional-elements" : "elements", read_only_elts);
114 elts = Accidental_placement::get_relevant_accidentals (read_only_elts, left);
117 elts = read_only_elts;
119 /* This is a special-case for NoteColumn: we want to include arpeggio in its
120 skyline (so spacing takes it into account) but we don't want to include it
121 in the NoteColumn's extent because some spanners (eg. Hairpin) bound themselves
122 on the NoteColumn and we don't want them to include arpeggios in their bounds.
124 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 "