SCM axis = scm_car (me->get_property ("axes"));
Axis ax = Axis (scm_to_int (axis));
- SCM force = me->get_property ("forced-distance");
- if (scm_is_number (force))
- Align_interface::align_to_fixed_distance (me, ax);
- else
- Align_interface::align_elements_to_extents (me, ax);
+ Align_interface::align_elements_to_extents (me, ax);
return SCM_BOOL_T;
}
/*
- merge with align-to-extents?
+ TODO: This belongs to the old two-pass spacing. Delete me.
*/
-MAKE_SCHEME_CALLBACK(Align_interface, stretch_after_break, 1)
+MAKE_SCHEME_CALLBACK (Align_interface, stretch_after_break, 1)
SCM
Align_interface::stretch_after_break (SCM grob)
{
Direction stacking_dir = robust_scm2dir (me->get_property ("stacking-dir"),
DOWN);
- Real delta = extra_space / elems.size() * stacking_dir;
+ Real delta = extra_space / elems.size () * stacking_dir;
for (vsize i = 0; i < elems.size (); i++)
elems[i]->translate_axis (i * delta, Y_AXIS);
}
return SCM_UNSPECIFIED;
}
- /*
- merge with align-to-extents?
- */
- void
- Align_interface::align_to_fixed_distance (Grob *me, Axis a)
- {
- Direction stacking_dir = robust_scm2dir (me->get_property ("stacking-dir"),
- DOWN);
-
- Real dy = robust_scm2double (me->get_property ("forced-distance"), 0.0);
-
- extract_grob_set (me, "elements", elem_source);
-
- vector<Grob*> elems (elem_source); // writable..
-
- Real where = 0;
-
- Interval v;
- v.set_empty ();
- vector<Real> translates;
-
- for (vsize j = elems.size (); j--;)
- {
- /*
- This is not very elegant, in that we need special support for
- hara-kiri. Unfortunately, the generic wiring of
- force_hara_kiri_callback () (extent and offset callback) is
- such that we might get into a loop if we call extent () or
- offset () the elements.
- */
- if (a == Y_AXIS
- && Hara_kiri_group_spanner::has_interface (elems[j]))
- Hara_kiri_group_spanner::consider_suicide (elems[j]);
-
- if (!elems[j]->is_live ())
- elems.erase (elems.begin () + j);
- }
-
- for (vsize j = 0; j < elems.size (); j++)
- {
- where += stacking_dir * dy;
- translates.push_back (where);
- v.unite (Interval (where, where));
- }
-
- for (vsize i = 0; i < translates.size (); i++)
- elems[i]->translate_axis (translates[i] - v.center (), a);
- }
-
/* for each grob, find its upper and lower skylines. If the grob has
an empty extent, delete it from the list instead. If the extent is
non-empty but there is no skyline available (or pure is true), just
for (vsize i = elements->size (); i--;)
{
Grob *g = (*elements)[i];
- Interval extent = g->maybe_pure_extent (g, a, pure, start, end);
- Interval other_extent = pure ? Interval (-infinity_f, infinity_f)
- : g->extent (common_refpoint, other_axis (a));
- Box b;
- b[a] = extent;
- b[other_axis (a)] = other_extent;
-
- if (extent.is_empty ())
- {
- elements->erase (elements->begin () + i);
- continue;
- }
-
Skyline_pair skylines;
- if (!pure
- && Skyline_pair::unsmob (g->get_property ("skylines")))
- skylines = *Skyline_pair::unsmob (g->get_property ("skylines"));
- else
- {
- if (!pure)
- programming_error ("no skylines for alignment-child\n");
-
- skylines = Skyline_pair (b, 0, other_axis (a));
- }
/* each skyline is calculated relative to (potentially) a different other_axis
coordinate. In order to compare the skylines effectively, we need to shift them
to some absolute reference point */
if (!pure)
{
+ Skyline_pair *skys = Skyline_pair::unsmob (g->get_property ("skylines"));
+ if (skys)
+ skylines = *skys;
+ else
+ programming_error ("no skylines for alignment-child\n");
+
/* this is perhaps an abuse of minimum-?-extent: maybe we should create
another property? But it seems that the only (current) use of
minimum-Y-extent is to separate vertically-aligned elements */
SCM min_extent = g->get_property (a == X_AXIS ? "minimum-X-extent" : "minimum-Y-extent");
+
if (is_number_pair (min_extent))
{
+ Box b;
+ Interval other_extent = g->extent (common_refpoint, other_axis (a));
b[a] = ly_scm2interval (min_extent);
- skylines.insert (b, 0, other_axis (a));
+ b[other_axis (a)] = other_extent;
+ if (!other_extent.is_empty ())
+ skylines.insert (b, 0, other_axis (a));
}
Real offset = child_refpoints[i]->relative_coordinate (common_refpoint, other_axis (a));
skylines.shift (offset);
}
+ else
+ {
+ assert (a == Y_AXIS);
+ Interval extent = g->pure_height (g, start, end);
+ if (!extent.is_empty ())
+ {
+ Box b;
+ b[a] = extent;
+ b[other_axis (a)] = Interval (-infinity_f, infinity_f);
+ skylines.insert (b, 0, other_axis (a));
+ }
+ }
-
- ret->push_back (skylines);
+ if (skylines.is_empty ())
+ elements->erase (elements->begin () + i);
+ else
+ ret->push_back (skylines);
}
reverse (*ret);
}
get_skylines (me, &elems, a, pure, start, end, &skylines);
Real where = 0;
+ /* TODO: extra-space stuff belongs to two-pass spacing. Delete me */
SCM extra_space_handle = scm_assq (ly_symbol2scm ("alignment-extra-space"), line_break_details);
Real extra_space = robust_scm2double (scm_is_pair (extra_space_handle)
? scm_cdr (extra_space_handle)
Real padding = robust_scm2double (me->get_property ("padding"), 0.0);
vector<Real> translates;
+ Skyline down_skyline (stacking_dir);
for (vsize j = 0; j < elems.size (); j++)
{
Real dy = 0;
if (j == 0)
dy = skylines[j][-stacking_dir].max_height ();
else
- dy = skylines[j-1][stacking_dir].distance (skylines[j][-stacking_dir]);
+ {
+ down_skyline.merge (skylines[j-1][stacking_dir]);
+ dy = down_skyline.distance (skylines[j][-stacking_dir]);
+ }
- where += stacking_dir * max (0.0, dy + padding + extra_space / elems.size ());
+ dy = max (0.0, dy + padding + extra_space / elems.size ());
+ down_skyline.raise (-stacking_dir * dy);
+ where += stacking_dir * dy;
translates.push_back (where);
}
all_grobs[j]->translate_axis (translates[j], a);
}
+ /* After we have already determined the y-offsets of our children, we may still
+ want to stretch them a little. */
+ void
+ Align_interface::stretch (Grob *me, Real amount, Axis a)
+ {
+ extract_grob_set (me, "elements", elts);
+ Real non_empty_elts = stretchable_children_count (me);
+ Real offset = 0.0;
+ Direction dir = robust_scm2dir (me->get_property ("stacking-dir"), DOWN);
+ for (vsize i = 0; i < elts.size (); i++)
+ {
+ elts[i]->translate_axis (dir * offset, a);
+ if (!elts[i]->extent (me, a).is_empty ()
+ && !to_boolean (elts[i]->get_property ("keep-fixed-while-stretching")))
+ offset += amount / non_empty_elts;
+ }
+ me->flush_extent_cache (Y_AXIS);
+ }
+
Real
Align_interface::get_pure_child_y_translation (Grob *me, Grob *ch, int start, int end)
{
ga->set_ordered (true);
}
+ int
+ Align_interface::stretchable_children_count (Grob const *me)
+ {
+ extract_grob_set (me, "elements", elts);
+ int ret = 0;
+
+ /* start at 1: we will never move the first child while stretching */
+ for (vsize i = 1; i < elts.size (); i++)
+ if (!to_boolean (elts[i]->get_property ("keep-fixed-while-stretching"))
+ && !elts[i]->extent (elts[i], Y_AXIS).is_empty ())
+ ret++;
+
+ return ret;
+ }
+
+ MAKE_SCHEME_CALLBACK (Align_interface, calc_max_stretch, 1)
+ SCM
+ Align_interface::calc_max_stretch (SCM smob)
+ {
+ Grob *me = unsmob_grob (smob);
+ Spanner *spanner_me = dynamic_cast<Spanner*> (me);
+ Real ret = 0;
+
+ if (spanner_me && stretchable_children_count (me) > 0)
+ {
+ Paper_column *left = dynamic_cast<Paper_column*> (spanner_me->get_bound (LEFT));
+ Real height = me->extent (me, Y_AXIS).length ();
+ SCM line_break_details = left->get_property ("line-break-system-details");
+ SCM fixed_offsets = scm_assq (ly_symbol2scm ("alignment-offsets"),
+ line_break_details);
+
+ /* if there are fixed offsets, we refuse to stretch */
+ if (fixed_offsets != SCM_BOOL_F)
+ ret = 0;
+ else
+ ret = height * height / 80.0; /* why this, exactly? -- jneem */
+ }
+ return scm_from_double (ret);
+ }
+
/*
Find Y-axis parent of G that has a #'forced-distance property. This
has the effect of finding the piano-staff given an object in that
piano staff.
+
+ FIXME: piano staves no longer have forced-distance. The code that
+ relies on this function (in line-spanner) is broken.
*/
Grob *
find_fixed_alignment_parent (Grob *g)
{
- while (g)
- {
- if (scm_is_number (g->get_property ("forced-distance")))
- return g;
-
- g = g->get_parent (Y_AXIS);
- }
-
+ (void) g;
+ programming_error ("deprecated. We don't use forced-distance anymore");
return 0;
}
"align-dir "
"axes "
"elements "
- "forced-distance "
"padding "
"positioning-done "
"stacking-dir "
for (vsize i = 0; i < elts.size (); i++)
{
Grob *se = elts[i];
- Interval dims = se->extent (common, a);
- if (!dims.is_empty ())
- r.unite (dims);
+ if (!to_boolean (se->get_property ("cross-staff")))
+ {
+ Interval dims = se->extent (common, a);
+ if (!dims.is_empty ())
+ r.unite (dims);
+ }
}
return r;
}
return common;
}
-MAKE_SCHEME_CALLBACK(Axis_group_interface,calc_x_common, 1);
+MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_x_common, 1);
SCM
Axis_group_interface::calc_x_common (SCM grob)
{
return common->self_scm ();
}
-MAKE_SCHEME_CALLBACK(Axis_group_interface,calc_y_common, 1);
+MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_y_common, 1);
SCM
Axis_group_interface::calc_y_common (SCM grob)
{
else if (priority_1 > priority_2)
return false;
+ /* if neither grob has an outside-staff priority, the ordering will have no
+ effect -- we just need to choose a consistent ordering. We do this to
+ avoid the side-effect of calculating extents. */
+ if (isinf (priority_1))
+ return g1 < g2;
+
/* if there is no preference in staff priority, choose the left-most one */
Grob *common = g1->common_refpoint (g2, X_AXIS);
Real start_1 = g1->extent (common, X_AXIS)[LEFT];
for (vsize i = 0; i < elements->size (); i++)
add_boxes (elements->grob (i), x_common, y_common, boxes);
}
- else if (!scm_is_number (me->get_property ("outside-staff-priority")))
+ else if (!scm_is_number (me->get_property ("outside-staff-priority"))
+ && !to_boolean (me->get_property ("cross-staff")))
boxes->push_back (Box (me->extent (x_common, X_AXIS),
me->extent (y_common, Y_AXIS)));
}
return skylines;
}
+ MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_max_stretch, 1)
+ SCM
+ Axis_group_interface::calc_max_stretch (SCM smob)
+ {
+ Grob *me = unsmob_grob (smob);
+ Real ret = 0;
+ extract_grob_set (me, "elements", elts);
+
+ for (vsize i = 0; i < elts.size (); i++)
+ if (Axis_group_interface::has_interface (elts[i]))
+ ret += robust_scm2double (elts[i]->get_property ("max-stretch"), 0.0);
+
+ return scm_from_double (ret);
+ }
+
ADD_INTERFACE (Axis_group_interface,
"An object that groups other layout objects.",
"Y-common "
"axes "
"elements "
+ "keep-fixed-while-stretching "
+ "max-stretch "
"pure-Y-common "
"pure-relevant-elements "
"skylines "
void
Bar_number_engraver::stop_translation_timestep ()
{
- if (text_)
- {
- text_->set_object ("side-support-elements",
- grob_list_to_grob_array (get_property ("stavesFound")));
- text_ = 0;
- }
+ text_ = 0;
}
void
}
-ADD_ACKNOWLEDGER(Bar_number_engraver,break_aligned);
-ADD_ACKNOWLEDGER(Bar_number_engraver,break_alignment);
+ADD_ACKNOWLEDGER (Bar_number_engraver, break_aligned);
+ADD_ACKNOWLEDGER (Bar_number_engraver, break_alignment);
ADD_TRANSLATOR (Bar_number_engraver,
/* doc */ "A bar number is created whenever measurePosition "
return best_start;
}
-MAKE_SCHEME_CALLBACK(Beam, calc_beaming, 1)
+MAKE_SCHEME_CALLBACK (Beam, calc_beaming, 1)
SCM
Beam::calc_beaming (SCM smob)
{
do
{
bool on_bound = (event_dir == LEFT) ? j == 0 :
- j == segs.size() - 1;
+ j == segs.size () - 1;
bool inside_stem = (event_dir == LEFT)
? segs[j].stem_index_ > 0
if (event_dir == RIGHT)
{
segments.push_back (current);
- current = Beam_segment();
+ current = Beam_segment ();
}
}
while (flip (&event_dir) != LEFT);
return segments;
}
-MAKE_SCHEME_CALLBACK(Beam, print, 1);
+MAKE_SCHEME_CALLBACK (Beam, print, 1);
SCM
Beam::print (SCM grob)
{
sets stem directions, a constant shift does not have an
influence.
*/
- head_extents += stem->relative_coordinate (common, Y_AXIS);
+ head_extents += stem->pure_relative_y_coordinate (common, 0, INT_MAX);
if (to_dir (stem->get_property_data ("direction")))
{
-MAKE_SCHEME_CALLBACK(Beam, calc_stem_shorten, 1)
+MAKE_SCHEME_CALLBACK (Beam, calc_stem_shorten, 1)
SCM
Beam::calc_stem_shorten (SCM smob)
{
Real dx = lvs->relative_coordinate (commonx, X_AXIS) - x0;
Drul_array<Real> pos = ly_scm2interval (posns);
-
scale_drul (&pos, Staff_symbol_referencer::staff_space (me));
Hmm. At this time, beam position and slope are determined. Maybe,
stem directions and length should set to relative to the chord's
position of the beam. */
-MAKE_SCHEME_CALLBACK(Beam, set_stem_lengths, 1);
+MAKE_SCHEME_CALLBACK (Beam, set_stem_lengths, 1);
SCM
Beam::set_stem_lengths (SCM smob)
{
return knee;
}
+ bool
+ Beam::is_cross_staff (Grob *me)
+ {
+ extract_grob_set (me, "stems", stems);
+ Grob *staff_symbol = Staff_symbol_referencer::get_staff_symbol (me);
+ for (vsize i = 0; i < stems.size (); i++)
+ if (Staff_symbol_referencer::get_staff_symbol (stems[i]) != staff_symbol)
+ return true;
+ return false;
+ }
+
+ MAKE_SCHEME_CALLBACK (Beam, cross_staff, 1)
+ SCM
+ Beam::cross_staff (SCM smob)
+ {
+ return scm_from_bool (is_cross_staff (unsmob_grob (smob)));
+ }
+
int
Beam::get_direction_beam_count (Grob *me, Direction d)
{
#include "warn.hh"
/*
- We use the following optimal substructure. Let W(A) be our weight function.
+ We use the following optimal substructure. Let W (A) be our weight function.
- Let A_{k,n} = (a_{k,n,1}, ... a_{k,n,k}) be the optimal set of line breaks
- for k systems and n potential breakpoints. a_{k,n,k} = n (it is the end of
+ Let A_{k, n} = (a_{k, n,1}, ... a_{k, n, k}) be the optimal set of line breaks
+ for k systems and n potential breakpoints. a_{k, n, k} = n (it is the end of
the piece)
Then A_{k+1, m} is contructed from
- min_ {k < j < m} ( W(A_{k,j} :: m) )
+ min_ {k < j < m} ( W (A_{k, j} :: m) )
where by A::m we denote appending m to the list A
Indices in the code:
The above algorithm makes it easy to end at a point before the end of the
- score (just find A_{k,m} for some m < breaks_.size () - 1). However, we must
+ score (just find A_{k, m} for some m < breaks_.size () - 1). However, we must
add information for starting at a point after the beginning. One constructor
allows the specification of a list of starting columns, start_. We then have
start_.size () different solution arrays. state_[i] is the array for the
. . . .
. . . .
where the X's mark invalid solutions (can't have more systems than
- breakpoints). Note that each value is of the form a_{x,n,x}. This is because
- a breakpoint of the form a_{x,n,x-1} will also be called a_{x-1,m,x-1} for
+ breakpoints). Note that each value is of the form a_{x, n, x}. This is because
+ a breakpoint of the form a_{x, n, x-1} will also be called a_{x-1, m, x-1} for
some m < n. Each cell in the array stores the value of its m (ie. the
ending breakpoint of the previous line) as "prev_".
- For finding A_{sys, brk}, let "me" be the (sys_count,brk) cell in our
+ For finding A_{sys, brk}, let "me" be the (sys_count, brk) cell in our
solution array (state_[start][sys * rank + brk]).
Then A_{sys, brk} = A_{sys - 1, me.prev_} :: me
return found_something;
}
- vector<Column_x_positions>
- Constrained_breaking::solve ()
- {
- if (!systems_)
- return get_best_solution (0, VPOS);
-
- resize (systems_);
- return get_solution (0, VPOS, systems_);
- }
+
Column_x_positions
Constrained_breaking::space_line (vsize i, vsize j)
{
Column_x_positions col;
vector<Grob*> line (all_.begin () + breaks_[i],
- all_.begin() + breaks_[j] + 1);
+ all_.begin () + breaks_[j] + 1);
Interval line_dims = line_dimensions_int (pscore_->layout (), i);
bool last = j == breaks_.size () - 1;
bool ragged = ragged_right || (last && ragged_last);
}
vector<Column_x_positions>
- Constrained_breaking::get_solution (vsize start, vsize end, vsize sys_count)
+ Constrained_breaking::solve (vsize start, vsize end, vsize sys_count)
{
vsize start_brk = starting_breakpoints_[start];
vsize end_brk = prepare_solution (start, end, sys_count);
}
}
/* if we get to here, just put everything on one line */
- warning (_ ("cannot find line breaking that satisfies constraints" ));
+ warning (_ ("cannot find line breaking that satisfies constraints"));
ret.push_back (space_line (0, end_brk));
return ret;
}
vector<Column_x_positions>
- Constrained_breaking::get_best_solution (vsize start, vsize end)
+ Constrained_breaking::best_solution (vsize start, vsize end)
{
- vsize min_systems = get_min_systems (start, end);
- vsize max_systems = get_max_systems (start, end);
+ vsize min_systems = min_system_count (start, end);
+ vsize max_systems = max_system_count (start, end);
Real best_demerits = infinity_f;
vector<Column_x_positions> best_so_far;
if (dem < best_demerits)
{
best_demerits = dem;
- best_so_far = get_solution (start, end, i);
+ best_so_far = solve (start, end, i);
}
else
{
- vector<Column_x_positions> cur = get_solution (start, end, i);
+ vector<Column_x_positions> cur = solve (start, end, i);
bool too_many_lines = true;
for (vsize j = 0; j < cur.size (); j++)
}
if (best_so_far.size ())
return best_so_far;
- return get_solution (start, end, max_systems);
+ return solve (start, end, max_systems);
}
std::vector<Line_details>
- Constrained_breaking::get_details (vsize start, vsize end, vsize sys_count)
+ Constrained_breaking::line_details (vsize start, vsize end, vsize sys_count)
{
vsize brk = prepare_solution (start, end, sys_count);
Matrix<Constrained_break_node> const &st = state_[start];
}
int
- Constrained_breaking::get_min_systems (vsize start, vsize end)
+ Constrained_breaking::min_system_count (vsize start, vsize end)
{
vsize sys_count;
vsize brk = prepare_solution (start, end, 1);
}
int
- Constrained_breaking::get_max_systems (vsize start, vsize end)
+ Constrained_breaking::max_system_count (vsize start, vsize end)
{
vsize brk = (end >= start_.size ()) ? breaks_.size () : starting_breakpoints_[end];
return brk - starting_breakpoints_[start];
line.force_ = forces[i*breaks_.size () + j];
if (ragged && last && !isinf (line.force_))
- line.force_ = 0;
+ line.force_ = (line.force_ < 0) ? infinity_f : 0;
if (isinf (line.force_))
break;
"before-line-breaking "
"cause "
"color "
+ "cross-staff "
"extra-X-extent "
"extra-Y-extent "
"extra-offset "
return grob_stencil_extent (me, Y_AXIS);
}
-MAKE_SCHEME_CALLBACK(Grob, y_parent_positioning, 1);
+MAKE_SCHEME_CALLBACK (Grob, y_parent_positioning, 1);
SCM
Grob::y_parent_positioning (SCM smob)
{
}
-MAKE_SCHEME_CALLBACK(Grob, x_parent_positioning, 1);
+MAKE_SCHEME_CALLBACK (Grob, x_parent_positioning, 1);
SCM
Grob::x_parent_positioning (SCM smob)
{
*/
#include "prob.hh"
+ #include "skyline.hh"
LY_DEFINE (ly_prob_set_property_x, "ly:prob-set-property!",
2, 1, 0, (SCM obj, SCM sym, SCM value),
{
LY_ASSERT_SMOB (Prob, obj, 1);
Prob *ps = unsmob_prob (obj);
- LY_ASSERT_TYPE (ly_is_symbol,sym, 2);
+ LY_ASSERT_TYPE (ly_is_symbol, sym, 2);
if (dfault == SCM_UNDEFINED)
dfault = SCM_EOL;
"If obj the specified prob-type?")
{
Prob*prob = unsmob_prob (obj);
- return scm_from_bool (prob && prob->type() == type);
+ return scm_from_bool (prob && prob->type () == type);
}
LY_DEFINE (ly_make_prob, "ly:make-prob",
}
-LY_DEFINE(ly_paper_system_p, "ly:paper-system?",
+LY_DEFINE (ly_paper_system_p, "ly:paper-system?",
1, 0, 0, (SCM obj),
"Type predicate.")
{
return ly_prob_type_p (obj, ly_symbol2scm ("paper-system"));
}
+
+ LY_DEFINE (ly_paper_system_minimum_distance, "ly:paper-system-minimum-distance",
+ 2, 0, 0, (SCM sys1, SCM sys2),
+ "Measure the minimum distance between these two paper-systems "
+ "using their stored skylines if possible and falling back to "
+ "their extents otherwise.")
+ {
+ Real ret = 0;
+ Prob *p1 = unsmob_prob (sys1);
+ Prob *p2 = unsmob_prob (sys2);
+ Skyline_pair *sky1 = Skyline_pair::unsmob (p1->get_property ("skylines"));
+ Skyline_pair *sky2 = Skyline_pair::unsmob (p2->get_property ("skylines"));
+
+ if (sky1 && sky2)
+ ret = (*sky1)[DOWN].distance ((*sky2)[UP]);
+ else
+ {
+ Stencil *s1 = unsmob_stencil (p1->get_property ("stencil"));
+ Stencil *s2 = unsmob_stencil (p2->get_property ("stencil"));
+ Interval iv1 = s1->extent (Y_AXIS);
+ Interval iv2 = s2->extent (Y_AXIS);
+ ret = iv2[UP] - iv1[DOWN];
+ }
+ return scm_from_double (ret);
+ }
void
Building::precompute ()
{
- slope_ = (height_[RIGHT] - height_[LEFT]) / (iv_.length());
+ slope_ = (height_[RIGHT] - height_[LEFT]) / (iv_.length ());
if (height_[LEFT] == height_[RIGHT]) /* in case they're both infinity */
slope_ = 0;
while (!buildings->empty ())
partials.push_back (non_overlapping_skyline (buildings));
- /* we'd like to say while (partials->size () > 1) but that's O(n).
+ /* we'd like to say while (partials->size () > 1) but that's O (n).
Instead, we exit in the middle of the loop */
while (!partials.empty ())
{
return out;
}
+ bool
+ Skyline::is_empty () const
+ {
+ return buildings_.empty ();
+ }
+
Skyline_pair::Skyline_pair ()
: skylines_ (Skyline (DOWN), Skyline (UP))
{
skylines_[DOWN].merge (other[DOWN]);
}
+ bool
+ Skyline_pair::is_empty () const
+ {
+ return skylines_[UP].is_empty ()
+ && skylines_[DOWN].is_empty ();
+ }
+
Skyline&
Skyline_pair::operator [] (Direction d)
{
SCM
Skyline::mark_smob (SCM)
{
- ASSERT_LIVE_IS_ALLOWED();
+ ASSERT_LIVE_IS_ALLOWED ();
return SCM_EOL;
}
-MAKE_SCHEME_CALLBACK(Slur, calc_direction, 1)
+MAKE_SCHEME_CALLBACK (Slur, calc_direction, 1)
SCM
Slur::calc_direction (SCM smob)
{
e->warning ("Ignoring grob for slur. avoid-slur not set?");
}
+ MAKE_SCHEME_CALLBACK (Slur, cross_staff, 1)
+ SCM
+ Slur::cross_staff (SCM smob)
+ {
+ Grob *me = unsmob_grob (smob);
+ Grob *staff = Staff_symbol_referencer::get_staff_symbol (me);
+ assert (staff); // delete me
+ extract_grob_set (me, "note-columns", cols);
+
+ for (vsize i = 0; i < cols.size (); i++)
+ if (Staff_symbol_referencer::get_staff_symbol (cols[i]) != staff)
+ return SCM_BOOL_T;
+ return SCM_BOOL_F;
+ }
ADD_INTERFACE (Slur,
if (!is_normal_stem (me))
return ly_interval2scm (iv);
+
+ /* if we are part of a cross-staff beam, return empty */
+ if (get_beam (me) && Beam::is_cross_staff (get_beam (me)))
+ return ly_interval2scm (iv);
Real ss = Staff_symbol_referencer::staff_space (me);
Real len = scm_to_double (calc_length (smob)) * ss / 2;
return (scm_is_number (s)) ? scm_to_int (s) : 2;
}
-MAKE_SCHEME_CALLBACK(Stem, calc_positioning_done, 1);
+MAKE_SCHEME_CALLBACK (Stem, calc_positioning_done, 1);
SCM
Stem::calc_positioning_done (SCM smob)
{
return SCM_BOOL_T;
}
-MAKE_SCHEME_CALLBACK(Stem, calc_direction, 1);
+MAKE_SCHEME_CALLBACK (Stem, calc_direction, 1);
SCM
Stem::calc_direction (SCM smob)
{
return scm_from_int (dir);
}
-MAKE_SCHEME_CALLBACK(Stem, calc_default_direction, 1);
+MAKE_SCHEME_CALLBACK (Stem, calc_default_direction, 1);
SCM
Stem::calc_default_direction (SCM smob)
{
}
/*
- Can't get_stencil(), since that would cache stencils too early.
+ Can't get_stencil (), since that would cache stencils too early.
This causes problems with beams.
*/
Stencil *stencil = unsmob_stencil (print (smob));
- Interval iv = stencil ? stencil->extent (Y_AXIS) : Interval();
+ Interval iv = stencil ? stencil->extent (Y_AXIS) : Interval ();
if (beam)
{
if (dir == CENTER)
return si;
}
-MAKE_SCHEME_CALLBACK(Stem, calc_stem_info, 1);
+MAKE_SCHEME_CALLBACK (Stem, calc_stem_info, 1);
SCM
Stem::calc_stem_info (SCM smob)
{
return le;
}
+ bool
+ Stem::is_cross_staff (Grob *stem)
+ {
+ Grob *beam = unsmob_grob (stem->get_object ("beam"));
+ return beam && Beam::is_cross_staff (beam);
+ }
+
+ MAKE_SCHEME_CALLBACK (Stem, cross_staff, 1)
+ SCM
+ Stem::cross_staff (SCM smob)
+ {
+ return scm_from_bool (is_cross_staff (unsmob_grob (smob)));
+ }
+
/* FIXME: Too many properties */
ADD_INTERFACE (Stem,
"The stem represent the graphical stem. "
grobs[i]->fixup_refpoint ();
}
- SCM
- System::get_paper_systems ()
+ void
+ System::do_break_substitution_and_fixup_refpoints ()
{
for (vsize i = 0; i < all_elements_->size (); i++)
{
if (be_verbose_global)
message (_f ("Element count %d.", count + element_count ()));
+ }
+
+ SCM
+ System::get_broken_system_grobs ()
+ {
+ SCM ret = SCM_EOL;
+ for (vsize i = 0; i < broken_intos_.size (); i++)
+ ret = scm_cons (broken_intos_[i]->self_scm (), ret);
+ return scm_reverse (ret);
+ }
+ SCM
+ System::get_paper_systems ()
+ {
SCM lines = scm_c_make_vector (broken_intos_.size (), SCM_EOL);
for (vsize i = 0; i < broken_intos_.size (); i++)
{
System *system = dynamic_cast<System *> (broken_intos_[i]);
- system->post_processing ();
- system->build_skylines ();
- if (i > 0)
- {
- System *prev = dynamic_cast<System*> (broken_intos_[i-1]);
- Real r = prev->skylines_[DOWN].distance (system->skylines_[UP]);
- system->set_property ("skyline-distance", scm_from_double (r));
- }
scm_vector_set_x (lines, scm_from_int (i),
system->get_paper_system ());
SCM exprs = SCM_EOL;
SCM *tail = &exprs;
+ post_processing ();
+ build_skylines ();
+
vector<Layer_entry> entries;
for (vsize j = 0; j < all_elements_->size (); j++)
{
Grob *g = entries[j].grob_;
Stencil st = g->get_print_stencil ();
- if (st.expr() == SCM_EOL)
+ if (st.expr () == SCM_EOL)
continue;
Offset o;
/* information that the page breaker might need */
Grob *right_bound = this->get_bound (RIGHT);
- pl->set_property ("skyline-distance", get_property ("skyline-distance"));
+ pl->set_property ("skylines", skylines_.smobbed_copy ());
pl->set_property ("page-break-permission", right_bound->get_property ("page-break-permission"));
pl->set_property ("page-turn-permission", right_bound->get_property ("page-turn-permission"));
pl->set_property ("page-break-penalty", right_bound->get_property ("page-break-penalty"));
pl->set_property ("page-turn-penalty", right_bound->get_property ("page-turn-penalty"));
- if (!scm_is_pair (pl->get_property ("refpoint-Y-extent")))
- {
- Interval staff_refpoints;
- staff_refpoints.set_empty ();
- extract_grob_set (this, "spaceable-staves", staves);
- for (vsize i = 0; i < staves.size (); i++)
- {
- Grob *g = staves[i];
- staff_refpoints.add_point (g->relative_coordinate (this, Y_AXIS));
- }
- pl->set_property ("refpoint-Y-extent", ly_interval2scm (staff_refpoints));
- }
+ Interval staff_refpoints;
+ extract_grob_set (this, "spaceable-staves", staves);
+ for (vsize i = 0; i < staves.size (); i++)
+ staff_refpoints.add_point (staves[i]->relative_coordinate (this, Y_AXIS));
+ pl->set_property ("staff-refpoint-extent", ly_interval2scm (staff_refpoints));
pl->set_property ("system-grob", this->self_scm ());
return pl->unprotect ();
return attachments;
}
-Tie_formatting_problem::Tie_formatting_problem()
+Tie_formatting_problem::Tie_formatting_problem ()
{
x_refpoint_ = 0;
}
x.add_point (stem->relative_coordinate (x_refpoint_, X_AXIS));
x.widen (staff_space / 20); // ugh.
Interval y;
- y.add_point (Stem::stem_end_position (stem) * staff_space * .5);
+ Real stem_end_position =
+ Stem::is_cross_staff (stem)
+ ? get_grob_direction (stem) * infinity_f
+ : Stem::stem_end_position (stem) * staff_space * .5;
+
+ y.add_point (stem_end_position);
Direction stemdir = get_grob_direction (stem);
y.add_point (Stem::head_positions (stem)[-stemdir]
*/
boxes.push_back (Box (x, y));
- stem_extents_[key].unite (Box (x,y));
+ stem_extents_[key].unite (Box (x, y));
if (dir == LEFT)
{
Box flag_box = Stem::get_translated_flag (stem).extent_box ();
- flag_box.translate( Offset (x[RIGHT], X_AXIS));
+ flag_box.translate ( Offset (x[RIGHT], X_AXIS));
boxes.push_back (flag_box);
}
}
}
extract_grob_set (stem, "note-heads", heads);
- for (vsize i = 0; i < heads.size(); i ++)
+ for (vsize i = 0; i < heads.size (); i ++)
{
- if (find (bounds.begin(), bounds.end (), dynamic_cast<Item*> (heads[i])) == bounds.end ())
+ if (find (bounds.begin (), bounds.end (), dynamic_cast<Item*> (heads[i])) == bounds.end ())
{
/*
other untied notes in the same chord.
{
Interval x;
Interval y;
- if (head_boxes.size())
+ if (head_boxes.size ())
{
Box b = boundary (head_boxes, updowndir, 0);
x = b[X_AXIS];
while (flip (&d) != LEFT);
if (ties_conf
- && ties_conf->size() == 1)
+ && ties_conf->size () == 1)
{
Direction d = LEFT;
Drul_array<Grob*> stems (0, 0);
);
vars.push_back (var);
}
- if (i == ties.size() && !specifications_[i].has_manual_position_
+ if (i == ties.size () && !specifications_[i].has_manual_position_
&& ties[i].dir_ == UP)
{
Tie_configuration_variation var;
if (to_boolean (x_refpoint_->layout ()
->lookup_variable (ly_symbol2scm ("debug-tie-scoring"))))
{
- for (vsize i = 0; i < base.size(); i++)
+ for (vsize i = 0; i < base.size (); i++)
{
string card = base.complete_tie_card (i);
specifications_[i].tie_grob_->set_property ("quant-score",