2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1998--2012 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, Y_AXIS, LEFT);
86 MAKE_SCHEME_CALLBACK (Separation_item, calc_skylines, 1);
88 Separation_item::calc_skylines (SCM smob)
90 Item *me = unsmob_item (smob);
91 vector<Box> bs = boxes (me, 0);
92 Skyline_pair sp (bs, Y_AXIS);
94 TODO: We need to decide if padding is 'intrinsic'
95 to a skyline or if it is something that is only added on in
96 distance calculations. Here, we make it intrinsic, which copies
97 the behavior from the old code but no longer corresponds to how
98 vertical skylines are handled (where padding is not built into
101 Real vp = robust_scm2double (me->get_property ("skyline-vertical-padding"), 0.0);
102 sp[LEFT] = sp[LEFT].padded (vp);
103 sp[RIGHT] = sp[RIGHT].padded (vp);
104 return sp.smobbed_copy ();
107 /* if left is non-NULL, get the boxes corresponding to the
108 conditional-elements (conditioned on the grob LEFT). This
109 sounds more general than it is: conditional-elements are
110 always accidentals attached to a tied note.
113 Separation_item::boxes (Grob *me, Grob *left)
115 Item *item = dynamic_cast<Item *> (me);
117 int very_large = INT_MAX;
118 Paper_column *pc = item->get_column ();
120 extract_grob_set (me, left ? "conditional-elements" : "elements", read_only_elts);
124 elts = Accidental_placement::get_relevant_accidentals (read_only_elts, left);
126 elts = read_only_elts;
128 Grob *ycommon = common_refpoint_of_array (elts, me, Y_AXIS);
130 for (vsize i = 0; i < elts.size (); i++)
132 Item *il = dynamic_cast<Item *> (elts[i]);
133 if (pc != il->get_column ())
136 /* ugh. We want to exclude groups of grobs (so that we insert each grob
137 individually into the skyline instead of adding a single box that
138 bounds all of them). However, we can't exclude an axis-group that
139 adds to its childrens' stencil. Currently, this is just TrillPitchGroup;
140 hence the check for note-head-interface. */
141 if (Axis_group_interface::has_interface (il)
142 && !Note_head::has_interface (il))
145 Interval y (il->pure_height (ycommon, 0, very_large));
146 Interval x (il->extent (pc, X_AXIS));
148 Interval extra_width = robust_scm2interval (elts[i]->get_property ("extra-spacing-width"),
149 Interval (-0.1, 0.1));
150 Interval extra_height = robust_scm2interval (elts[i]->get_property ("extra-spacing-height"),
151 Interval (0.0, 0.0));
153 x[LEFT] += extra_width[LEFT];
154 x[RIGHT] += extra_width[RIGHT];
155 y[DOWN] += extra_height[DOWN];
156 y[UP] += extra_height[UP];
158 if (!x.is_empty () && !y.is_empty ())
159 out.push_back (Box (x, y));
165 MAKE_SCHEME_CALLBACK (Separation_item, print, 1)
167 Separation_item::print (SCM smob)
172 Grob *me = unsmob_grob (smob);
174 if (Skyline_pair *s = Skyline_pair::unsmob (me->get_property ("horizontal-skylines")))
176 ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[LEFT].to_points (Y_AXIS)).in_color (255, 255, 0));
177 ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[RIGHT].to_points (Y_AXIS)).in_color (0, 255, 255));
179 return ret.smobbed_copy ();
182 ADD_INTERFACE (Separation_item,
183 "Item that computes widths to generate spacing rods.",
187 "conditional-elements "
190 "horizontal-skylines "
191 "skyline-vertical-padding "