2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1998--2009 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 return Skyline (bs, 0.1, 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 /* todo: the horizon_padding is somewhat arbitrary */
94 return Skyline_pair (bs, 0.1, 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)) {
129 Grob *ycommon = common_refpoint_of_array (elts, me, Y_AXIS);
131 for (vsize i = 0; i < elts.size (); i++)
133 Item *il = dynamic_cast<Item *> (elts[i]);
134 if (pc != il->get_column ())
137 /* ugh. We want to exclude groups of grobs (so that we insert each grob
138 individually into the skyline instead of adding a single box that
139 bounds all of them). However, we can't exclude an axis-group that
140 adds to its childrens' stencil. Currently, this is just TrillPitchGroup;
141 hence the check for note-head-interface. */
142 if (Axis_group_interface::has_interface (il)
143 && !Note_head::has_interface (il))
146 Interval y (il->pure_height (ycommon, 0, very_large));
147 Interval x (il->extent (pc, X_AXIS));
149 Interval extra_width = robust_scm2interval (elts[i]->get_property ("extra-spacing-width"),
150 Interval (-0.1, 0.1));
151 Interval extra_height = robust_scm2interval (elts[i]->get_property ("extra-spacing-height"),
152 Interval (-0.1, 0.1));
154 x[LEFT] += extra_width[LEFT];
155 x[RIGHT] += extra_width[RIGHT];
156 y[DOWN] += extra_height[DOWN];
157 y[UP] += extra_height[UP];
159 if (!x.is_empty () && !y.is_empty ())
160 out.push_back (Box (x, y));
166 MAKE_SCHEME_CALLBACK (Separation_item, print, 1)
168 Separation_item::print (SCM smob)
173 Grob *me = unsmob_grob (smob);
175 if (Skyline_pair *s = Skyline_pair::unsmob (me->get_property ("horizontal-skylines")))
177 ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[LEFT].to_points (Y_AXIS)).in_color (255, 255, 0));
178 ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[RIGHT].to_points (Y_AXIS)).in_color (0, 255, 255));
180 return ret.smobbed_copy ();
183 ADD_INTERFACE (Separation_item,
184 "Item that computes widths to generate spacing rods.",
188 "conditional-elements "
191 "horizontal-skylines "