This saves time in the compliation of scores with long line widths.
+++ /dev/null
-/*
- This file is part of LilyPond, the GNU music typesetter.
-
- Copyright (C) 2011--2012 Mike Solomon <mike@apollinemike.com>
-
- LilyPond is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- LilyPond is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <cstdio>
-
-#include "column-description.hh"
-#include "paper-column.hh"
-#include "simple-spacer.hh"
-#include "spaceable-grob.hh"
-#include "spring.hh"
-
-static Grob *
-next_spaceable_column (vector<Grob *> const &list, vsize starting)
-{
- for (vsize i = starting + 1; i < list.size (); i++)
- if (!Paper_column::is_loose (list[i]))
- return list[i];
- return 0;
-}
-
-Column_description
-Column_description::get_column_description (vector<Grob *> const &cols, vsize col_index, bool line_starter)
-{
- Grob *col = cols[col_index];
- if (line_starter)
- col = Item::maybe_find_prebroken_piece (dynamic_cast<Item *> (col), RIGHT);
-
- Column_description description;
- Grob *next_col = next_spaceable_column (cols, col_index);
- if (next_col)
- description.spring_ = Spaceable_grob::get_spring (col, next_col);
-
- Grob *end_col = dynamic_cast<Item *> (cols[col_index + 1])->find_prebroken_piece (LEFT);
- if (end_col)
- description.end_spring_ = Spaceable_grob::get_spring (col, end_col);
-
- for (SCM s = Spaceable_grob::get_minimum_distances (col);
- scm_is_pair (s); s = scm_cdr (s))
- {
- Grob *other = unsmob_grob (scm_caar (s));
- vsize j = binary_search (cols, other, Paper_column::less_than, col_index);
- if (j != VPOS)
- {
- if (cols[j] == other)
- description.rods_.push_back (Rod_description (j, scm_to_double (scm_cdar (s))));
- else /* it must end at the LEFT prebroken_piece */
- description.end_rods_.push_back (Rod_description (j, scm_to_double (scm_cdar (s))));
- }
- }
-
- if (!line_starter && to_boolean (col->get_property ("keep-inside-line")))
- description.keep_inside_line_ = col->extent (col, X_AXIS);
-
- description.break_permission_ = col->get_property ("line-break-permission");
- return description;
-}
\ No newline at end of file
breaks_ = pscore_->get_break_indices ();
all_ = pscore_->root_system ()->used_columns ();
lines_.resize (breaks_.size (), breaks_.size (), Line_details ());
- vector<Simple_spacer> spacers
- = pscore_->root_system ()->get_simple_spacers (other_lines.length (),
- other_lines.length () - first_line.length (),
- ragged_right_);
+ vector<Real> forces = get_line_forces (all_,
+ other_lines.length (),
+ other_lines.length () - first_line.length (),
+ ragged_right_);
for (vsize i = 0; i + 1 < breaks_.size (); i++)
{
for (vsize j = i + 1; j < breaks_.size (); j++)
bool ragged = ragged_right_ || (last && ragged_last_);
Line_details &line = lines_.at (j, i);
- line.force_ = spacers[i * breaks_.size () + j].force_penalty (ragged_right_);
- if (!spacers[i * breaks_.size () + j].fits ())
- {
- if (spacers[i * breaks_.size () + j].minimal_)
- line.force_ = -200000;
- else
- line.force_ = infinity_f;
- }
+ line.force_ = forces[i * breaks_.size () + j];
if (ragged && last && !isinf (line.force_))
line.force_ = (line.force_ < 0 && j > i + 1) ? infinity_f : 0;
- if (!line.force_ && !spacers[i * breaks_.size () + j].line_len ())
- line.force_ = infinity_f;
if (isinf (line.force_))
break;
+++ /dev/null
-/*
- This file is part of LilyPond, the GNU music typesetter.
-
- Copyright (C) 2011--2012 Mike Solomon <mike@apollinemike.com>
-
- LilyPond is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- LilyPond is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef COLUMN_DESCRIPTION_HH
-#define COLUMN_DESCRIPTION_HH
-
-#include "lily-proto.hh"
-#include "smobs.hh"
-#include "spring.hh"
-
-struct Rod_description
-{
- vsize r_;
- Real dist_;
-
- bool operator < (const Rod_description r)
- {
- return r_ < r.r_;
- }
-
- Rod_description ()
- {
- r_ = 0;
- dist_ = 0;
- }
-
- Rod_description (vsize r, Real d)
- {
- r_ = r;
- dist_ = d;
- }
-};
-
-struct Column_description
-{
- vector<Rod_description> rods_;
- vector<Rod_description> end_rods_; /* use these if they end at the last column of the line */
- Spring spring_;
- Spring end_spring_;
-
- SCM break_permission_;
- Interval keep_inside_line_;
-
- Column_description ()
- {
- break_permission_ = SCM_EOL;
- }
- static Column_description get_column_description (vector<Grob *> const &cols, vsize col_index, bool line_starter);
-};
-
-#endif /* COLUMN_DESCRIPTION_HH */
static bool is_non_musical (Grob *);
static bool break_visible (Grob *);
- static Item *maybe_find_prebroken_piece (Item *g, Direction d);
+
bool is_broken () const;
virtual bool pure_is_visible (int start, int end) const;
DECLARE_GROB_INTERFACE ();
static int get_rank (Grob const *);
- static bool is_loose (Grob *);
static bool is_musical (Grob *);
static Moment when_mom (Grob *);
static bool is_used (Grob *);
public:
Simple_spacer ();
- bool minimal_;
-
void solve (Real line_len, bool ragged);
void add_rod (int l, int r, Real dist);
void add_spring (Spring const &);
void set_force (Real force);
Real force () const;
- Real line_len () const;
Real force_penalty (bool ragged) const;
bool fits () const;
DECLARE_SIMPLE_SMOBS (Simple_spacer);
private:
-
Real expand_line ();
Real compress_line ();
Real rod_force (int l, int r, Real dist);
bool fits_;
};
+/* returns a vector of dimensions breaks.size () * breaks.size () */
+vector<Real> get_line_forces (vector<Grob *> const &columns,
+ Real line_len,
+ Real indent,
+ bool ragged);
+
Column_x_positions get_line_configuration (vector<Grob *> const &columns,
Real line_len,
Real indent,
class System : public Spanner
{
int rank_;
- vector<Simple_spacer> simple_spacers_;
Grob_array *all_elements_;
void init_elements ();
friend class Paper_score; // ugh.
Grob *get_pure_bound (Direction dir, int start, int end);
Grob *get_maybe_pure_bound (Direction dir, bool pure, int start, int end);
int get_rank () const;
- vector<Simple_spacer> get_simple_spacers (Real line_len, Real indent, bool ragged);
- void gen_simple_spacers (Real line_len, Real indent, bool ragged);
vector<Real> get_footnote_heights_in_range (vsize st, vsize end);
vector<Real> get_in_note_heights_in_range (vsize st, vsize end);
vector<Real> internal_get_note_heights_in_range (vsize st, vsize end, bool foot);
return 0;
}
-Item *
-Item::maybe_find_prebroken_piece (Item *g, Direction d)
-{
- Item *ret = g->find_prebroken_piece (d);
- if (ret)
- return ret;
- return g;
-}
-
Item *
Item::find_prebroken_piece (Direction d) const
{
return Moment (0);
}
-bool
-Paper_column::is_loose (Grob *g)
-{
- return (scm_is_pair (g->get_object ("between-cols")));
-}
-
bool
Paper_column::is_musical (Grob *me)
{
#include <cstdio>
-#include "column-description.hh"
#include "column-x-positions.hh"
#include "dimensions.hh"
#include "international.hh"
return force_;
}
-Real
-Simple_spacer::line_len () const
-{
- return line_len_;
-}
-
bool
Simple_spacer::fits () const
{
/****************************************************************/
+struct Rod_description
+{
+ vsize r_;
+ Real dist_;
+
+ bool operator < (const Rod_description r)
+ {
+ return r_ < r.r_;
+ }
+
+ Rod_description ()
+ {
+ r_ = 0;
+ dist_ = 0;
+ }
+
+ Rod_description (vsize r, Real d)
+ {
+ r_ = r;
+ dist_ = d;
+ }
+};
+
+struct Column_description
+{
+ vector<Rod_description> rods_;
+ vector<Rod_description> end_rods_; /* use these if they end at the last column of the line */
+ Spring spring_;
+ Spring end_spring_;
+
+ SCM break_permission_;
+ Interval keep_inside_line_;
+
+ Column_description ()
+ {
+ break_permission_ = SCM_EOL;
+ }
+};
+
+static bool
+is_loose (Grob *g)
+{
+ return (scm_is_pair (g->get_object ("between-cols")));
+}
+
+static Grob *
+maybe_find_prebroken_piece (Grob *g, Direction d)
+{
+ Grob *ret = dynamic_cast<Item *> (g)->find_prebroken_piece (d);
+ if (ret)
+ return ret;
+ return g;
+}
+
+static Grob *
+next_spaceable_column (vector<Grob *> const &list, vsize starting)
+{
+ for (vsize i = starting + 1; i < list.size (); i++)
+ if (!is_loose (list[i]))
+ return list[i];
+ return 0;
+}
+
+static Column_description
+get_column_description (vector<Grob *> const &cols, vsize col_index, bool line_starter)
+{
+ Grob *col = cols[col_index];
+ if (line_starter)
+ col = maybe_find_prebroken_piece (col, RIGHT);
+
+ Column_description description;
+ Grob *next_col = next_spaceable_column (cols, col_index);
+ if (next_col)
+ description.spring_ = Spaceable_grob::get_spring (col, next_col);
+
+ Grob *end_col = dynamic_cast<Item *> (cols[col_index + 1])->find_prebroken_piece (LEFT);
+ if (end_col)
+ description.end_spring_ = Spaceable_grob::get_spring (col, end_col);
+
+ for (SCM s = Spaceable_grob::get_minimum_distances (col);
+ scm_is_pair (s); s = scm_cdr (s))
+ {
+ Grob *other = unsmob_grob (scm_caar (s));
+ vsize j = binary_search (cols, other, Paper_column::less_than, col_index);
+ if (j != VPOS)
+ {
+ if (cols[j] == other)
+ description.rods_.push_back (Rod_description (j, scm_to_double (scm_cdar (s))));
+ else /* it must end at the LEFT prebroken_piece */
+ description.end_rods_.push_back (Rod_description (j, scm_to_double (scm_cdar (s))));
+ }
+ }
+
+ if (!line_starter && to_boolean (col->get_property ("keep-inside-line")))
+ description.keep_inside_line_ = col->extent (col, X_AXIS);
+
+ description.break_permission_ = col->get_property ("line-break-permission");
+ return description;
+}
+
+vector<Real>
+get_line_forces (vector<Grob *> const &columns,
+ Real line_len, Real indent, bool ragged)
+{
+ vector<vsize> breaks;
+ vector<Real> force;
+ vector<Grob *> non_loose;
+ vector<Column_description> cols;
+ SCM force_break = ly_symbol2scm ("force");
+
+ for (vsize i = 0; i < columns.size (); i++)
+ if (!is_loose (columns[i]) || Paper_column::is_breakable (columns[i]))
+ non_loose.push_back (columns[i]);
+
+ breaks.clear ();
+ breaks.push_back (0);
+ cols.push_back (Column_description ());
+ for (vsize i = 1; i + 1 < non_loose.size (); i++)
+ {
+ if (Paper_column::is_breakable (non_loose[i]))
+ breaks.push_back (cols.size ());
+
+ cols.push_back (get_column_description (non_loose, i, false));
+ }
+ breaks.push_back (cols.size ());
+ force.resize (breaks.size () * breaks.size (), infinity_f);
+
+ for (vsize b = 0; b + 1 < breaks.size (); b++)
+ {
+ cols[breaks[b]] = get_column_description (non_loose, breaks[b], true);
+ vsize st = breaks[b];
+
+ for (vsize c = b + 1; c < breaks.size (); c++)
+ {
+ vsize end = breaks[c];
+ Simple_spacer spacer;
+
+ for (vsize i = breaks[b]; i < end - 1; i++)
+ spacer.add_spring (cols[i].spring_);
+ spacer.add_spring (cols[end - 1].end_spring_);
+
+ for (vsize i = breaks[b]; i < end; i++)
+ {
+ for (vsize r = 0; r < cols[i].rods_.size (); r++)
+ if (cols[i].rods_[r].r_ < end)
+ spacer.add_rod (i - st, cols[i].rods_[r].r_ - st, cols[i].rods_[r].dist_);
+ for (vsize r = 0; r < cols[i].end_rods_.size (); r++)
+ if (cols[i].end_rods_[r].r_ == end)
+ spacer.add_rod (i - st, end - st, cols[i].end_rods_[r].dist_);
+ if (!cols[i].keep_inside_line_.is_empty ())
+ {
+ spacer.add_rod (i - st, end - st, cols[i].keep_inside_line_[RIGHT]);
+ spacer.add_rod (0, i - st, -cols[i].keep_inside_line_[LEFT]);
+ }
+ }
+ spacer.solve ((b == 0) ? line_len - indent : line_len, ragged);
+ force[b * breaks.size () + c] = spacer.force_penalty (ragged);
+
+ if (!spacer.fits ())
+ {
+ if (c == b + 1)
+ force[b * breaks.size () + c] = -200000;
+ else
+ force[b * breaks.size () + c] = infinity_f;
+ break;
+ }
+ if (end < cols.size () && cols[end].break_permission_ == force_break)
+ break;
+ }
+ }
+ return force;
+}
+
Column_x_positions
get_line_configuration (vector<Grob *> const &columns,
Real line_len,
ret.cols_.push_back (dynamic_cast<Item *> (columns[0])->find_prebroken_piece (RIGHT));
for (vsize i = 1; i + 1 < columns.size (); i++)
{
- if (Paper_column::is_loose (columns[i]))
+ if (is_loose (columns[i]))
ret.loose_cols_.push_back (columns[i]);
else
ret.cols_.push_back (columns[i]);
the end_XXX_ fields of our column_description */
for (vsize i = 0; i + 1 < ret.cols_.size (); i++)
{
- cols.push_back (Column_description::get_column_description (ret.cols_, i, i == 0));
+ cols.push_back (get_column_description (ret.cols_, i, i == 0));
spacer.add_spring (cols[i].spring_);
}
for (vsize i = 0; i < cols.size (); i++)
return ret;
}
+
#include "ly-smobs.icc"
IMPLEMENT_SIMPLE_SMOBS (Simple_spacer);
#include "all-font-metrics.hh"
#include "axis-group-interface.hh"
#include "break-align-interface.hh"
-#include "column-description.hh"
#include "grob-array.hh"
#include "hara-kiri-group-spanner.hh"
#include "international.hh"
return 0;
}
-vector<Simple_spacer>
-System::get_simple_spacers (Real line_len, Real indent, bool ragged)
-{
- if (!simple_spacers_.size ())
- gen_simple_spacers (line_len, indent, ragged);
-
- return simple_spacers_;
-}
-
-void
-System::gen_simple_spacers (Real line_len, Real indent, bool ragged)
-{
- vector<vsize> breaks;
- vector<Grob *> non_loose;
- vector<Column_description> cols;
- SCM force_break = ly_symbol2scm ("force");
- vector<Grob *> columns = used_columns ();
-
- for (vsize i = 0; i < columns.size (); i++)
- if (!Paper_column::is_loose (columns[i])
- || Paper_column::is_breakable (columns[i]))
- non_loose.push_back (columns[i]);
-
- breaks.clear ();
- breaks.push_back (0);
- cols.push_back (Column_description ());
- for (vsize i = 1; i + 1 < non_loose.size (); i++)
- {
- if (Paper_column::is_breakable (non_loose[i]))
- breaks.push_back (cols.size ());
-
- cols.push_back (Column_description::get_column_description (non_loose, i, false));
- }
- breaks.push_back (cols.size ());
- simple_spacers_.resize (breaks.size () * breaks.size (), Simple_spacer ());
-
- for (vsize b = 0; b + 1 < breaks.size (); b++)
- {
- cols[breaks[b]] = Column_description::get_column_description (non_loose, breaks[b], true);
- vsize st = breaks[b];
-
- for (vsize c = b + 1; c < breaks.size (); c++)
- {
- vsize end = breaks[c];
- Simple_spacer spacer;
-
- for (vsize i = breaks[b]; i < end - 1; i++)
- spacer.add_spring (cols[i].spring_);
- spacer.add_spring (cols[end - 1].end_spring_);
-
- for (vsize i = breaks[b]; i < end; i++)
- {
- for (vsize r = 0; r < cols[i].rods_.size (); r++)
- if (cols[i].rods_[r].r_ < end)
- spacer.add_rod (i - st, cols[i].rods_[r].r_ - st, cols[i].rods_[r].dist_);
- for (vsize r = 0; r < cols[i].end_rods_.size (); r++)
- if (cols[i].end_rods_[r].r_ == end)
- spacer.add_rod (i - st, end - st, cols[i].end_rods_[r].dist_);
- if (!cols[i].keep_inside_line_.is_empty ())
- {
- spacer.add_rod (i - st, end - st, cols[i].keep_inside_line_[RIGHT]);
- spacer.add_rod (0, i - st, -cols[i].keep_inside_line_[LEFT]);
- }
- }
- spacer.solve ((b == 0) ? line_len - indent : line_len, ragged);
- spacer.minimal_ = c == b + 1;
- simple_spacers_[b * breaks.size () + c] = spacer;
-
- if (!spacer.fits ()
- || (end < cols.size ()
- && cols[end].break_permission_ == force_break))
- break;
- }
- }
-}
-
Interval
System::pure_refpoint_extent (vsize start, vsize end)
{