]> git.donarmstrong.com Git - lilypond.git/commitdiff
*** empty log message ***
authorJoe Neeman <joeneeman@gmail.com>
Mon, 4 Sep 2006 05:31:28 +0000 (05:31 +0000)
committerJoe Neeman <joeneeman@gmail.com>
Mon, 4 Sep 2006 05:31:28 +0000 (05:31 +0000)
22 files changed:
ChangeLog
input/mutopia/J.S.Bach/baerenreiter-sarabande.ly
lily/axis-group-interface.cc
lily/constrained-breaking.cc
lily/gourlay-breaking.cc [deleted file]
lily/grob.cc
lily/include/gourlay-breaking.hh [deleted file]
lily/include/lily-guile.hh
lily/include/simple-spacer.hh
lily/include/slur.hh
lily/lily-guile.cc
lily/optimal-page-breaking.cc
lily/page-breaking.cc
lily/page-spacing.cc
lily/page-turn-page-breaking.cc
lily/paper-score.cc
lily/simple-spacer.cc
lily/slur.cc
lily/system.cc
ly/paper-defaults.ly
scm/define-grobs.scm
scm/layout-page-layout.scm

index 94f62b8cceb80e4b9d8b0023be6eb887ad26a102..ff27e6840b940e8b69c23c44fa4675959db8453e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,55 @@
+2006-09-02  Joe Neeman  <joeneeman@gmail.com>
+
+       * lily/simple-spacer.cc (get_line_forces): Ignore loose columns
+       unless they are breakable. This fixes discrepancies between the forces
+       calculated here and the forces calculated in get_line_configuration.
+
+       * lily/grob.cc (pure_relative_y_coordinate): fix some
+       mis-estimation that was happening with piano staves.
+
+       * lily/constrained-breaking.cc (resize): don't choke if we get a
+       measure that won't fit on a line.
+       (combine_demerits): don't consider uniformity when ragged
+
+       * lily/page-spacing.cc (solve): why the f* were there two of these?
+       (calc_subproblem): properly handle the case where a system is taller
+       than the page.
+
+       * lily/system.cc (get_paper_system): ensure that all the permissions
+       and penalties are passed to the paper systems.
+
+       * lily/page-breaking.cc (create_system_list): support system-count.
+
+       * scm/define-grobs.scm (pure-print-callbacks): add
+       ly:script-interface::print
+
+       * lily/page-spacing.cc (min_page_count): fix calculation of min
+       pages if we are ragged and there are non-zero springs.
+
+       * scm/layout-page-layout.scm: if the pure-height estimates are under
+       the real height, allow space-systems to ignore padding if it is
+       needed in order to fit the systems on one page
+
+       * lily/optimal-page-breaking.cc (try_page_spacing): fix reading
+       ragged properties
+       (solve): fix performance problem. Make sure we always get at least
+       one solution
+
+       * lily/page-breaking.cc (make_pages): include write-page-breaks
+       and page-stencil
+
+       * lily/paper-score.cc (calc_breaking): remove Gourlay breaker
+
+       * scm/define-grobs.scm: add the new slur-callback
+       fix pure-relevant to not exclude grobs whose extent is already
+       calculated
+
+       * ly/paper-defaults.ly: make ly:optimal-breaking the new default
+       page breaker
+
+       * lily/slur.cc (pure_height): new callback to estimate the height
+       of a slur
+
 2006-09-02  Graham Percival  <gpermus@gmail.com>
 
        * Documentation/user/invoking.itely: small update on
index bc4ce8a241e9925ade3af7c2c0eef50be68d92a1..a61a1ff8a6168dc9c5da6ad6dd849d35cf15b0f9 100644 (file)
@@ -126,7 +126,7 @@ sarabandeA =  \context Voice  \relative c {
   d'[ cis] |
   %%  d4 d,,2 |
   d4
-  #(assert-system-count-override 6)
+%  #(assert-system-count-override 6)
   d,,2 |
 }
 
@@ -173,6 +173,7 @@ smallerPaper = \layout {
   line-width =183.5 \mm
   between-system-space = 25\mm 
   between-system-padding = 0\mm
+  system-count = 6
 
 %%  annotatespacing = ##t
 }
index 1d509f04d1923b436c0f4866d2767e2b085fea32..8700da3e544d181b0acb81bb988721eb19fc3e74 100644 (file)
@@ -145,7 +145,14 @@ Axis_group_interface::relative_pure_height (Grob *me,
        {
          Interval dims = elts[i]->pure_height (common, start, end);
          if (!dims.is_empty ())
-           r.unite (dims);
+           {
+             r.unite (dims);
+             /*
+             message (_f ("axis-group (%d-%d) %s has child %s with height (%.2f,%.2f), my height is now (%.2f,%.2f)",
+                          start, end,
+                          me->name ().c_str (), elts[i]->name ().c_str (), dims[DOWN], dims[UP], r[DOWN], r[UP]));
+             */
+           }
        }
     }
   return r;
index e3b07fab3ba52868ad9e1aaa65b0b795174079f8..4d9c5795eea42d6d80b159c8af1804b8c6e03d2f 100644 (file)
@@ -156,7 +156,6 @@ Constrained_breaking::resize (vsize systems)
       all_ = pscore_->root_system ()->columns ();
       lines_.resize (breaks_.size (), breaks_.size (), Line_details ());
       vector<Real> forces = get_line_forces (all_,
-                                            breaks_,
                                             other_lines.length (),
                                             other_lines.length () - first_line.length (),
                                             ragged_right);
@@ -172,6 +171,12 @@ Constrained_breaking::resize (vsize systems)
              bool ragged = ragged_right || (last && ragged_last);
              Line_details &line = lines_.at (j, i);
 
+             line.force_ = forces[i*breaks_.size () + j];
+             if (ragged && last && !isinf (line.force_))
+               line.force_ = 0;
+             if (isinf (line.force_))
+               break;
+
              Grob *c = all_[breaks_[j]];
              line.break_penalty_ = robust_scm2double (c->get_property ("line-break-penalty"), 0);
              line.page_penalty_ = robust_scm2double (c->get_property ("page-break-penalty"), 0);
@@ -181,15 +186,10 @@ Constrained_breaking::resize (vsize systems)
              line.turn_permission_ = c->get_property ("page-turn-permission");
 
              max_ext = max (max_ext, extent.length ());
-              line.force_ = forces[i*breaks_.size () + j];
               line.extent_ = extent;
               line.padding_ = padding;
               line.space_ = space;
               line.inverse_hooke_ = 1;
-             if (ragged && line.force_ < 0)
-               line.force_ = infinity_f;
-              if (isinf (line.force_))
-                break;
             }
        }
 
@@ -374,6 +374,9 @@ Constrained_breaking::Constrained_breaking (vector<vsize> const &start)
 Real
 Constrained_breaking::combine_demerits (Real force, Real prev_force)
 {
+  if (to_boolean (pscore_->layout ()->c_variable ("ragged-right")))
+    return force * force;
+
   return force * force + (prev_force - force) * (prev_force - force);
 }
 
diff --git a/lily/gourlay-breaking.cc b/lily/gourlay-breaking.cc
deleted file mode 100644 (file)
index f5e29ad..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
-  gourlay-breaking.cc -- implement Gourlay_breaking
-
-  source file of the GNU LilyPond music typesetter
-
-  (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
-*/
-
-#include "gourlay-breaking.hh"
-
-#include <cmath>               // rint
-#include <cstdio>
-using namespace std;
-
-#include "international.hh"
-#include "main.hh"
-#include "output-def.hh"
-#include "paper-column.hh"
-#include "paper-score.hh"
-#include "simple-spacer.hh"
-#include "system.hh"
-#include "warn.hh"
-
-/// How often to print operator pacification marks?
-const int HAPPY_DOTS = 3;
-
-/**
-   Helper to trace back an optimal path
-*/
-struct Break_node
-{
-  /** this was the previous. If negative, this break should not be
-      considered: this path has infinite energy
-
-  */
-  int prev_break_;
-  /**
-     Which system number so far?
-  */
-  int line_;
-
-  Real demerits_;
-  Column_x_positions line_config_;
-
-  Break_node ()
-  {
-    prev_break_ = -1;
-    line_ = 0;
-    demerits_ = 0;
-  }
-
-  void print () const
-  {
-    printf ("prev break %d, line %d, demerits %f\n",
-           prev_break_, line_, demerits_);
-  }
-};
-
-void
-print_break_nodes (vector<Break_node> const &arr)
-{
-  for (vsize i = 0; i < arr.size (); i++)
-    {
-      printf ("node %d: ", i);
-      arr[i].print ();
-    }
-}
-
-/**
-   This algorithms is adapted from the OSU Tech report on breaking lines.
-
-   this function is longish, but not very complicated.
-
-   TODO: should rewrite. See the function in scm/page-layout.scm for
-   inspiration.
-*/
-vector<Column_x_positions>
-Gourlay_breaking::solve () 
-{
-  vector<Break_node> optimal_paths;
-  vector<Grob*> all
-    = pscore_->root_system ()->columns ();
-
-  vector<vsize> breaks = pscore_->find_break_indices ();
-
-  Break_node first_node;
-  optimal_paths.push_back (first_node);
-
-  bool ragged_right = to_boolean (pscore_->layout ()->c_variable ("ragged-right"));
-  bool ragged_last = to_boolean (pscore_->layout ()->c_variable ("ragged-last"));
-
-  Real worst_force = 0.0;
-  for (vsize break_idx = 1; break_idx < breaks.size (); break_idx++)
-    {
-      /*
-       start with a short line, add measures. At some point
-       the line becomes infeasible. Then we don't try to add more
-      */
-      int minimal_start_idx = -1;
-      Column_x_positions minimal_sol;
-      Column_x_positions backup_sol;
-
-      Real minimal_demerits = infinity_f;
-
-      for (vsize start_idx = break_idx; start_idx--;)
-       {
-         vector<Grob*> line (all.begin () + breaks[start_idx],
-                             all.begin () + breaks[break_idx] + 1);
-
-         Interval line_dims
-           = line_dimensions_int (pscore_->layout (), optimal_paths[start_idx].line_);
-         bool last_line = break_idx == breaks.size () - 1;
-         bool ragged = ragged_right || (last_line && ragged_last);
-
-         Column_x_positions cp = get_line_configuration (line, line_dims[RIGHT] - line_dims[LEFT],
-                                                         line_dims[LEFT], ragged);
-
-         if (ragged && last_line)
-           cp.force_ = min (cp.force_, 0.0);
-
-         if (fabs (cp.force_) > worst_force)
-           worst_force = fabs (cp.force_);
-
-         /*
-           We remember this solution as a "should always work
-           solution", in case everything fucks up.  */
-         if (start_idx == break_idx - 1)
-           backup_sol = cp;
-
-         Real this_demerits;
-
-         if (optimal_paths[start_idx].demerits_ >= infinity_f)
-           this_demerits = infinity_f;
-         else
-           this_demerits = combine_demerits (optimal_paths[start_idx].line_config_, cp)
-             + optimal_paths[start_idx].demerits_;
-
-         if (this_demerits < minimal_demerits)
-           {
-             minimal_start_idx = start_idx;
-             minimal_sol = cp;
-             minimal_demerits = this_demerits;
-           }
-
-         /*
-           we couldn't satisfy the constraints, this won't get better
-           if we add more columns, so we get on with the next one
-         */
-         if (!cp.satisfies_constraints_)
-           break;
-       }
-
-      Break_node bnod;
-      if (minimal_start_idx < 0)
-       {
-         bnod.demerits_ = infinity_f;
-         bnod.line_config_ = backup_sol;
-         bnod.prev_break_ = break_idx - 1;
-       }
-      else
-       {
-         bnod.prev_break_ = minimal_start_idx;
-         bnod.demerits_ = minimal_demerits;
-         bnod.line_config_ = minimal_sol;
-       }
-      bnod.line_ = optimal_paths[bnod.prev_break_].line_ + 1;
-      optimal_paths.push_back (bnod);
-
-      if (! (break_idx % HAPPY_DOTS))
-       progress_indication (string ("[") + to_string (break_idx) + "]");
-    }
-
-  /* do the last one */
-  if (breaks.size () % HAPPY_DOTS)
-    progress_indication (string ("[") + to_string (breaks.size ()) + "]");
-
-  progress_indication ("\n");
-
-  vector<int> final_breaks;
-  vector<Column_x_positions> lines;
-
-  /* skip 0-th element, since it is a "dummy" elt*/
-  for (vsize i = optimal_paths.size () - 1; i > 0;)
-    {
-      final_breaks.push_back (i);
-      vsize prev = optimal_paths[i].prev_break_;
-      assert (i > prev);
-      i = prev;
-    }
-
-  if (be_verbose_global)
-    {
-      message (_f ("Optimal demerits: %f",
-                  optimal_paths.back ().demerits_) + "\n");
-    }
-
-  if (optimal_paths.back ().demerits_ >= infinity_f)
-    warning (_ ("no feasible line breaking found"));
-
-  for (vsize i = final_breaks.size (); i--;)
-    {
-      Column_x_positions cp (optimal_paths[final_breaks[i]].line_config_);
-
-      lines.push_back (cp);
-      if (!cp.satisfies_constraints_)
-       warning (_ ("can't find line breaking that satisfies constraints"));
-    }
-  return lines;
-}
-
-Gourlay_breaking::Gourlay_breaking ()
-{
-}
-
-/*
-  TODO: uniformity parameter to control rel. importance of spacing differences.
-
-  TODO:
-
-  mixing break penalties and constraint-failing solutions is confusing.
-*/
-Real
-Gourlay_breaking::combine_demerits (Column_x_positions const &prev,
-                                   Column_x_positions const &this_one) const
-{
-  Real break_penalties = 0.0;
-  Grob *pc = this_one.cols_.back ();
-  if (pc->original ())
-    {
-      SCM pen = pc->get_property ("line-break-penalty");
-      if (scm_is_number (pen) && fabs (scm_to_double (pen)) < 10000)
-       break_penalties += scm_to_double (pen);
-    }
-
-  /*
-    Q: do we want globally non-cramped lines, or locally equally
-    cramped lines?
-
-    There used to be an example file input/test/uniform-breaking to
-    demonstrate problems with this approach. When music is gradually
-    becoming denser, the uniformity requirement makes lines go from
-    cramped to even more cramped (because going from cramped
-    3meas/line to relatively loose 2meas/line is such a big step.
-
-  */
-
-  Real demerit = abs (this_one.force_) + abs (prev.force_ - this_one.force_)
-    + break_penalties;
-
-  if (!this_one.satisfies_constraints_)
-    {
-      /*
-       If it doesn't satisfy constraints, we make this one
-       really unattractive.
-
-       add 20000 to the demerits, so that a break penalty
-       of -10000 won't change the result */
-      demerit = max ((demerit + 20000), 2000.0);
-
-      demerit *= 10;
-    }
-
-  return demerit;
-}
-
index 4b44231e6195e72fe4357db4d55b018e12bfd337..72b46376c61d5405d8648c34b7b677db2b8327f1 100644 (file)
@@ -302,10 +302,14 @@ Grob::pure_relative_y_coordinate (Grob const *refp, int start, int end)
       dim_cache_[Y_AXIS].offset_ = 0;
     }
 
-  /* we simulate positioning-done if we are the child of a VerticalAlignment */
+  /* we simulate positioning-done if we are the child of a VerticalAlignment,
+     but only if we don't have a cached offset. If we do have a cached offset,
+     it probably means that the Alignment was fixed and it has already been
+     calculated.
+  */
   Grob *p = get_parent (Y_AXIS);
   Real trans = 0;
-  if (Align_interface::has_interface (p))
+  if (Align_interface::has_interface (p) && !dim_cache_[Y_AXIS].offset_)
     trans = Align_interface::get_pure_child_y_translation (p, this, start, end);
 
   return off + trans
diff --git a/lily/include/gourlay-breaking.hh b/lily/include/gourlay-breaking.hh
deleted file mode 100644 (file)
index 34a92f8..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-  gourlay-breaking.hh -- declare Gourlay_breaking
-
-  source file of the GNU LilyPond music typesetter
-
-  (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
-*/
-
-#ifndef GOURLAY_BREAKING_HH
-#define GOURLAY_BREAKING_HH
-
-#include "break-algorithm.hh"
-
-/**
-   A dynamic programming solution to breaking scores into lines
-*/
-struct Gourlay_breaking : public Break_algorithm
-{
-  vector<Column_x_positions> solve ();
-  Gourlay_breaking ();
-  Real combine_demerits (Column_x_positions const &, Column_x_positions const &) const;
-};
-#endif // GOURLAY_BREAKING_HH
index 23b3c64785edef95c978f2553d734da4a394f8a3..a0ac54bda718ac7566fdbac48b7a23424a6562a7 100644 (file)
@@ -117,9 +117,7 @@ inline SCM ly_append4 (SCM x1, SCM x2, SCM x3, SCM x4)
 /*
   display and print newline.
 */
-extern "C" {
-  void ly_display_scm (SCM s);
-}
+void ly_display_scm (void *s);
 
 void read_lily_scm_file (string);
 void ly_c_init_guile ();
index 39d9a3f853062cfd3eab5f0654fddd30f9e01fd2..758cd65b32c26a4809325f2dc7ed8a0a3f2f392b 100644 (file)
@@ -67,7 +67,6 @@ private:
 
 /* returns a vector of dimensions breaks.size () * breaks.size () */
 vector<Real> get_line_forces (vector<Grob*> const &columns,
-                             vector<vsize> breaks,
                              Real line_len,
                              Real indent,
                              bool ragged);
index 2c797239ce2876acf221f692dbe492ded0970657..f0213372bc1e740a0f87b02356268e4dedf2103a 100644 (file)
@@ -23,6 +23,7 @@ public:
   DECLARE_SCHEME_CALLBACK (print, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_control_points, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_direction, (SCM));
+  DECLARE_SCHEME_CALLBACK (pure_height, (SCM, SCM, SCM));
   DECLARE_SCHEME_CALLBACK (height, (SCM));
   DECLARE_SCHEME_CALLBACK (outside_slur_callback, (SCM, SCM));
   static bool has_interface (Grob *);
index 971063e54ec382c823785f5833e5caa61f99df34..064ed54fabe32b27c46e99ef33e56017f0a2c3e0 100644 (file)
@@ -114,15 +114,12 @@ gulp_file_to_string (string fn, bool must_exist, int size)
   return result;
 }
 
-extern "C" {
-  // maybe gdb 5.0 becomes quicker if it doesn't do fancy C++ typing?
-  void
-  ly_display_scm (SCM s)
-  {
-    scm_display (s, scm_current_output_port ());
-    scm_newline (scm_current_output_port ());
-  }
-};
+void
+ly_display_scm (void *s)
+{
+  scm_display ((SCM)s, scm_current_output_port ());
+  scm_newline (scm_current_output_port ());
+}
 
 string
 ly_scm2string (SCM str)
index 6f3fcc5683124a6e6915673fa4b00f79b48fe030..03d72629a01ea7c080345614e2a44cb5a09440cf 100644 (file)
@@ -39,8 +39,8 @@ Optimal_page_breaking::try_page_spacing (Line_division const &line_count)
   Real page_h = page_height (1, false); // FIXME
   SCM force_sym = ly_symbol2scm ("blank-last-page-force");
   Real blank_force = robust_scm2double (book_->paper_->lookup_variable (force_sym), 0);
-  bool ragged_all = book_->paper_->c_variable ("ragged-bottom");
-  bool ragged_last = book_->paper_->c_variable ("ragged-last-bottom");
+  bool ragged_all = to_boolean (book_->paper_->c_variable ("ragged-bottom"));
+  bool ragged_last = to_boolean (book_->paper_->c_variable ("ragged-last-bottom"));
   Spacing_result ret = space_systems_on_best_pages (lines,
                                                    page_h,
                                                    blank_force,
@@ -91,13 +91,13 @@ Optimal_page_breaking::solve ()
        {
          Spacing_result cur = try_page_spacing (div[d]);
          cur_page_count = cur.systems_per_page_.size ();
-         if (cur.demerits_ < best.demerits_)
+         if (cur.demerits_ < best.demerits_ || isinf (best.demerits_))
            {
              best = cur;
              best_division = div[d];
            }
 
-         if (cur.demerits_ < this_best_demerits)
+         if (cur.demerits_ < this_best_demerits || isinf (best.demerits_))
            {
              this_best_demerits = cur.demerits_;
              lower_bound = div[d];
@@ -110,7 +110,7 @@ Optimal_page_breaking::solve ()
              all_lines_stretched = false;
 
          if (all_lines_stretched)
-           max_page_count = cur_page_count + 1;
+           max_page_count = min (max_page_count, cur_page_count + 1);
        }
     }
 
index 1a32d7e7f1135d55c6e1e0dfcd47aa7275e95ca3..b1fd686e2b05aafff4c074dab0ef6516eb3cd5ed 100644 (file)
@@ -175,9 +175,17 @@ Page_breaking::breakpoint_property (vsize breakpoint, char const *str)
 SCM
 Page_breaking::make_pages (vector<vsize> lines_per_page, SCM systems)
 {
-  SCM module = scm_c_resolve_module ("scm layout-page-layout");
-  SCM make_page = scm_c_module_lookup (module, "make-page-from-systems");
+  SCM layout_module = scm_c_resolve_module ("scm layout-page-layout");
+  SCM dump_module = scm_c_resolve_module ("scm layout-page-dump");
+  SCM page_module = scm_c_resolve_module ("scm page");
+
+  SCM make_page = scm_c_module_lookup (layout_module, "make-page-from-systems");
+  SCM write_page_breaks = scm_c_module_lookup (dump_module, "write-page-breaks");
+  SCM page_stencil = scm_c_module_lookup (page_module, "page-stencil");
   make_page = scm_variable_ref (make_page);
+  write_page_breaks = scm_variable_ref (write_page_breaks);
+  page_stencil = scm_variable_ref (page_stencil);
+
   SCM book = book_->self_scm ();
   bool ragged_all = to_boolean (book_->paper_->c_variable ("ragged-bottom"));
   bool ragged_last = to_boolean (book_->paper_->c_variable ("ragged-last-bottom"));
@@ -193,10 +201,15 @@ Page_breaking::make_pages (vector<vsize> lines_per_page, SCM systems)
       SCM page = scm_apply_0 (make_page,
                              scm_list_n (book, lines, page_num, ragged, last, SCM_UNDEFINED));
 
+      scm_apply_1 (page_stencil, page, SCM_EOL);
       ret = scm_cons (page, ret);
       systems = scm_list_tail (systems, line_count);
     }
-  return scm_reverse (ret);
+  ret = scm_reverse (ret);
+
+  if (to_boolean (book_->paper_->c_variable ("write-page-layout")))
+    scm_apply_1 (write_page_breaks, ret, SCM_EOL);
+  return ret;
 }
 
 /* The page-turn-page-breaker needs to have a line-breaker between any two
@@ -214,7 +227,16 @@ Page_breaking::create_system_list ()
   for (SCM s = specs; s != SCM_EOL; s = scm_cdr (s))
     {
       if (Paper_score *ps = dynamic_cast<Paper_score*> (unsmob_music_output (scm_car (s))))
-       all_.push_back (System_spec (ps));
+       {
+         SCM system_count = ps->layout ()->c_variable ("system-count");
+
+         if (scm_is_number (system_count))
+           s = scm_append (scm_list_3 (scm_list_1 (scm_car (s)),
+                                       scm_vector_to_list (ps->get_paper_systems ()),
+                                       scm_cdr (s)));
+         else
+           all_.push_back (System_spec (ps));
+       }
       else
         {
           Prob *pb = unsmob_prob (scm_car (s));
index fc6c5b3ddfcc76f2f171f743e1ae5325e8245372..4d11f0c86595cf5b68b8ba52e59bd2fa9e0dc779 100644 (file)
@@ -8,7 +8,9 @@
 */
 
 #include "page-spacing.hh"
+
 #include "matrix.hh"
+#include "warn.hh"
 
 /*
   A much simplified rods-and-springs problem.
@@ -249,10 +251,10 @@ Page_spacer::solve (vsize page_count)
   vsize system = lines_.size () - 1;
 
   if (isinf (state_.at (system, page_count-1).demerits_))
-    return Spacing_result (); /* bad number of pages */
-
-  if (isinf (state_.at (system, page_count-1).demerits_))
-    return Spacing_result (); /* bad number of pages */
+    {
+      programming_error ("tried to space systems on a bad number of pages");
+      return Spacing_result (); /* bad number of pages */
+    }
 
   ret.penalty_ = state_.at (system, page_count-1).penalty_
     + lines_.back ().page_penalty_ + lines_.back ().turn_penalty_;
@@ -311,6 +313,10 @@ Page_spacer::calc_subproblem (vsize page, vsize line)
          if (line == lines_.size () - 1 && ragged_last_ && space.force_ > 0)
            space.force_ = 0;
 
+         /* we may have to deal with single lines that are taller than a page */
+         if (isinf (space.force_) && page_start == line)
+           space.force_ = -200000;
+
          Real dem = fabs (space.force_) + (prev ? prev->demerits_ : 0);
          Real penalty = 0;
          if (page_start > 0)
@@ -318,7 +324,7 @@ Page_spacer::calc_subproblem (vsize page, vsize line)
              + (page % 2 == 0) ? lines_[page_start-1].turn_penalty_ : 0;
 
          dem += penalty;
-         if (dem < cur.demerits_)
+         if (dem < cur.demerits_ || page_start == line)
            {
              cur.demerits_ = dem;
              cur.force_ = space.force_;
@@ -343,15 +349,15 @@ min_page_count (vector<Line_details> const &lines, Real page_height, bool ragged
   for (vsize i = 0; i < lines.size (); i++)
     {
       Real ext_len = lines[i].extent_.length ();
-      Real next_height = cur_rod_height
-       + (ragged ? max (ext_len, lines[i].space_) : ext_len)
-       + ((i > 0 && cur_rod_height > 0) ? lines[i-1].padding_: 0);
+      Real next_height = cur_rod_height + ext_len
+       + (ragged ? lines[i].space_ : 0)
+       + ((cur_rod_height > 0) ? lines[i-1].padding_: 0);
 
       if ((next_height > page_height && cur_rod_height > 0)
          || (i > 0 && lines[i-1].page_permission_ == ly_symbol2scm ("force")))
        {
          ret++;
-         cur_rod_height = ragged ? max (ext_len, lines[i].space_) : ext_len;
+         cur_rod_height = ext_len + (ragged ? lines[i].space_ : 0);
        }
       else
        cur_rod_height = next_height;
index 6171adca4d1e4455ee22b740b1fd0f7281b0fb5e..7db8831905237469fe51ec9d259addc3896affa2 100644 (file)
@@ -149,7 +149,7 @@ Page_turn_page_breaking::calc_subproblem (vsize ending_breakpoint)
               if (cur.page_count_ > 2 &&
                  (start < end - 1 || (!isinf (this_start_best.demerits_)
                                       && cur.page_count_ + cur.page_count_ % 2
-                                         > this_start_best.page_count_ + this_start_best.page_count_ % 2)))
+                                      > this_start_best.page_count_ + this_start_best.page_count_ % 2)))
                 {
                   ok_page = false;
                   break;
@@ -175,8 +175,9 @@ Page_turn_page_breaking::calc_subproblem (vsize ending_breakpoint)
           assert (!isinf (best.demerits_) && start < end - 1);
           break;
         }
+
       if (this_start_best.demerits_ < best.demerits_)
-        best = this_start_best;
+       best = this_start_best;
     }
   state_.push_back (best);
 }
index ffad13c38b076c0b0b171f0abd24b096e1336f59..e7a5f51247a9ac69ae1c6ffa603881255cc22c9f 100644 (file)
@@ -10,7 +10,6 @@
 
 #include "all-font-metrics.hh"
 #include "book.hh"
-#include "gourlay-breaking.hh"
 #include "international.hh"
 #include "main.hh"
 #include "misc.hh"
@@ -100,24 +99,17 @@ Paper_score::get_columns () const
 vector<Column_x_positions>
 Paper_score::calc_breaking ()
 {
-  Break_algorithm *algorithm = 0;
+  Constrained_breaking algorithm;
   vector<Column_x_positions> sol;
 
   message (_ ("Calculating line breaks...") + " ");
 
   int system_count = robust_scm2int (layout ()->c_variable ("system-count"), 0);
   if (system_count)
-    {
-      Constrained_breaking *b = new Constrained_breaking;
-      b->resize (system_count);
-      algorithm = b;
-    }
-  else
-    algorithm = new Gourlay_breaking;
+    algorithm.resize (system_count);
   
-  algorithm->set_pscore (this);
-  sol = algorithm->solve ();
-  delete algorithm;
+  algorithm.set_pscore (this);
+  sol = algorithm.solve ();
 
   return sol;
 }
index 3b3eaed3ba0ced4a4621ef5d7674736318db79e3..560dfecacdb080ecd277cd55a99f3d02a6254b91 100644 (file)
@@ -358,20 +358,6 @@ next_spaceable_column (vector<Grob*> const &list, vsize starting)
   return 0;
 }
 
-/* this only returns non-NULL if the line-ending column is the next
-   spaceable-or-breakable column */
-static Grob*
-next_line_ending_column (vector<Grob*> const &list, vsize starting)
-{
-  vsize i = starting + 1;
-  for (; i < list.size ()
-        && is_loose (list[i])
-        && !Paper_column::is_breakable (list[i]);
-       i++)
-    ;
-  return dynamic_cast<Item*> (list[i])->find_prebroken_piece (LEFT);
-}
-
 static void
 get_column_spring (Grob *this_col, Grob *next_col, Real *ideal, Real *inv_hooke)
 {
@@ -406,7 +392,7 @@ get_column_description (vector<Grob*> const &cols, vsize col_index, bool line_st
   Grob *next_col = next_spaceable_column (cols, col_index);
   if (next_col)
     get_column_spring (col, next_col, &description.ideal_, &description.inverse_hooke_);
-  Grob *end_col = next_line_ending_column (cols, col_index);
+  Grob *end_col = dynamic_cast<Item*> (cols[col_index+1])->find_prebroken_piece (LEFT);
   if (end_col)
     get_column_spring (col, end_col, &description.end_ideal_, &description.end_inverse_hooke_);
 
@@ -430,32 +416,35 @@ get_column_description (vector<Grob*> const &cols, vsize col_index, bool line_st
 }
 
 vector<Real>
-get_line_forces (vector<Grob*> const &icols, vector<vsize> breaks,
+get_line_forces (vector<Grob*> const &columns,
                 Real line_len, Real indent, bool ragged)
 {
+  vector<vsize> breaks;
   vector<Real> force;
-  force.resize (breaks.size () * breaks.size (), infinity_f);
-
+  vector<Grob*> non_loose;
   vector<Column_description> cols;
-  vsize b = 1;
   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 < icols.size () - 1; i++)
+  for (vsize i = 1; i < non_loose.size () - 1; i++)
     {
-      if (b < breaks.size () && breaks[b] == i)
-       {
-         breaks[b] = cols.size ();
-         b++;
-       }
-      if (!is_loose (icols[i]))
-       cols.push_back (get_column_description (icols, i, false));
+      if (Paper_column::is_breakable (non_loose[i]))
+       breaks.push_back (cols.size ());
+
+      cols.push_back (get_column_description (non_loose, i, false));
     }
-  breaks.back () = cols.size ();
+  breaks.push_back (cols.size ());
+  force.resize (breaks.size () * breaks.size (), infinity_f);
 
   for (vsize b = 0; b < breaks.size () - 1; b++)
     {
-      cols[breaks[b]] = get_column_description (icols, breaks[b], true);
+      cols[breaks[b]] = get_column_description (non_loose, breaks[b], true);
       vsize st = breaks[b];
 
       for (vsize c = b+1; c < breaks.size (); c++)
@@ -465,7 +454,7 @@ get_line_forces (vector<Grob*> const &icols, vector<vsize> breaks,
 
          for (vsize i = breaks[b]; i < end - 1; i++)
            spacer.add_spring (cols[i].ideal_, cols[i].inverse_hooke_);
-         spacer.add_spring (cols[end-1].end_ideal_, cols[end-1].inverse_hooke_);
+         spacer.add_spring (cols[end-1].end_ideal_, cols[end-1].end_inverse_hooke_);
 
 
          for (vsize i = breaks[b]; i < end; i++)
@@ -490,13 +479,16 @@ get_line_forces (vector<Grob*> const &icols, vector<vsize> breaks,
             breaks, so compression penalties can result in scores (eg. wtk-fugue) blowing
             up to too many pages. */
          Real f = spacer.force ();
-         force[b * breaks.size () + c] = f - (f < 0 ? f*f*6 : 0);
+         force[b * breaks.size () + c] = f - (f < 0 ? f*f*f*f*4 : 0);
 
          if (end < cols.size () && cols[end].break_permission_ == force_break)
            break;
          if (!spacer.fits ())
            {
-             force[b * breaks.size () + c] = infinity_f;
+             if (c == b + 1)
+               force[b * breaks.size () + c] = -200000;
+             else
+               force[b * breaks.size () + c] = infinity_f;
              break;
            }
        }
@@ -535,6 +527,7 @@ get_line_configuration (vector<Grob*> const &columns,
     {
       for (vsize r = 0; r < cols[i].rods_.size (); r++)
        spacer.add_rod (i, cols[i].rods_[r].r_, cols[i].rods_[r].dist_);
+
       if (!cols[i].keep_inside_line_.is_empty ())
        {
          spacer.add_rod (i, cols.size (), cols[i].keep_inside_line_[RIGHT]);
index 557200b239f47b9ad9b3f481783b9369ec73e772..0c68a6137e5be1891bf260da27f9e0a8b612aff6 100644 (file)
@@ -57,6 +57,35 @@ Slur::calc_direction (SCM smob)
   return scm_from_int (d);
 }
 
+MAKE_SCHEME_CALLBACK (Slur, pure_height, 3);
+SCM
+Slur::pure_height (SCM smob, SCM start_scm, SCM end_scm)
+{
+  Grob *me = unsmob_grob (smob);
+  int start = scm_to_int (start_scm);
+  int end = scm_to_int (end_scm);
+  Real height = robust_scm2double (me->get_property ("height-limit"), 2.0);
+
+  extract_grob_set (me, "note-columns", encompasses);
+  Interval ret;
+
+  Grob *parent = me->get_parent (Y_AXIS);
+  if (common_refpoint_of_array (encompasses, me, Y_AXIS) != parent)
+    /* this could happen if, for example, we are a cross-staff slur.
+       in this case, we want to be ignored */
+    return ly_interval2scm (Interval ());
+
+  for (vsize i = 0; i < encompasses.size (); i++)
+    {
+      Interval d = encompasses[i]->pure_height (parent, start, end);
+      if (!d.is_empty ())
+       ret.unite (d);
+    }
+
+  ret.widen (height * 0.5);
+  return ly_interval2scm (ret);
+}
+
 MAKE_SCHEME_CALLBACK (Slur, height, 1);
 SCM
 Slur::height (SCM smob)
index 2fba41a49e9f6e04b92f6a66cf428ea2338273a6..54562cdc04be4608b83f0a4c8e48f6ff0772f8f2 100644 (file)
@@ -397,14 +397,12 @@ System::get_paper_system ()
   Prob *pl = make_paper_system (prop_init);
   paper_system_set_stencil (pl, sys_stencil);
 
-  /* backwards-compatibility hack for the old page-breaker */
-  SCM turn_perm = left_bound->get_property ("page-break-permission");
-  if (!scm_is_symbol (turn_perm))
-    pl->set_property ("penalty", scm_from_double (10001.0));
-  else if (turn_perm == ly_symbol2scm ("force"))
-    pl->set_property ("penalty", scm_from_double (-10001.0));
-  else
-    pl->set_property ("penalty", scm_from_double (0.0));
+  /* information that the page breaker might need */
+  Grob *right_bound = this->get_bound (RIGHT);
+  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")))
     {
index 9fae0cabd55ccaad0748f6eea25b7f88b98b8a99..2e265c7ab189a2a8121aee2510e1984915fa7c6f 100644 (file)
@@ -96,7 +96,7 @@
        (baseline-skip . 3)
        (word-space . 0.6)))
 
-    #(define page-breaking optimal-page-breaks)
+    #(define page-breaking ly:optimal-breaking)
 %    #(define page-music-height default-page-music-height )
 %    #(define page-make-stencil default-page-make-stencil )
 
index bc3aee5e9359e7082468cb764c03c45f586ed737..07971e2f91bcfbf5da139b56bf60c007124d51f8 100644 (file)
   (list
    `(,ly:note-head::print . '())
    `(,ly:clef::print . '())
-   `(,ly:text-interface::print . '())))
+   `(,ly:text-interface::print . '())
+   `(,ly:script-interface::print . '())))
 
 ;; ly:grob::stencil-extent is safe iff the print callback is safe too
 (define (pure-stencil-height grob start stop)
    `(,ly:grob::stencil-height . ,pure-stencil-height)
    `(,ly:side-position-interface::y-aligned-side . ,ly:side-position-interface::pure-y-aligned-side)
    `(,ly:axis-group-interface::height . ,ly:axis-group-interface::pure-height)
-   `(,ly:hara-kiri-group-spanner::y-extent . ,ly:hara-kiri-group-spanner::pure-height)))
+   `(,ly:hara-kiri-group-spanner::y-extent . ,ly:hara-kiri-group-spanner::pure-height)
+   `(,ly:slur::height . ,ly:slur::pure-height)))
 
 (define pure-Y-offsets
   (list
 (define-public (pure-relevant grob)
   (let ((extent-callback (ly:grob-property-data grob 'Y-extent)))
     (or
+     (pair? extent-callback)
      (pair? (assq extent-callback pure-Y-extents))
      (and
       (pair? (assq extent-callback Y-extent-conversions))
index 215b5003d02e074ed9521a66e581888a53f379b1..fabe89f97b9caebe5ca163b89e089500d545ae0f 100644 (file)
    (ly:output-def-lookup layout 'between-system-padding)))
 
 
-(define (line-minimum-distance line next-line layout)
+(define (line-minimum-distance line next-line layout ignore-padding)
   "Minimum distance between `line' reference position and `next-line'
  reference position. If next-line is #f, return #f."
   (and next-line
        (max 0 (- (+ (interval-end (paper-system-extent next-line Y))
-                    (line-next-padding line next-line layout))
+                    (if ignore-padding 0 (line-next-padding line next-line layout)))
                  (interval-start (paper-system-extent line Y))))))
 
-(define (line-ideal-distance line next-line layout)
+(define (line-ideal-distance line next-line layout ignore-padding)
   "Ideal distance between `line' reference position and `next-line'
  reference position. If next-line is #f, return #f."
   (and next-line
        (+ (max 0 (- (+ (interval-end (paper-system-staff-extents next-line))
-                       (line-next-padding line next-line layout))
+                       (if ignore-padding 0 (line-next-padding line next-line layout)))
                     (interval-start (paper-system-staff-extents line))))
           (line-next-space line next-line layout))))
 
           (interval-end (paper-system-staff-extents line)))
        (interval-end (paper-system-extent line Y))))
 
-(define (line-ideal-relative-position line prev-line layout)
+(define (line-ideal-relative-position line prev-line layout ignore-padding)
   "Return ideal position of `line', relative to `prev-line' position.
   `prev-line' can be #f, meaning that `line' is the first line."
   (if (not prev-line)
       ;; first line on page
       (first-line-position line layout)
       ;; not the first line on page
-      (max (line-minimum-distance prev-line line layout)
-           (line-ideal-distance prev-line line layout))))
+      (max (line-minimum-distance prev-line line layout ignore-padding)
+           (line-ideal-distance prev-line line layout ignore-padding))))
 
-(define (line-minimum-relative-position line prev-line layout)
+(define (line-minimum-relative-position line prev-line layout ignore-padding)
   "Return position of `line', relative to `prev-line' position.
   `prev-line' can be #f, meaning that `line' is the first line."
   (if (not prev-line)
       ;; first line on page
       (first-line-position line layout)
       ;; not the first line on page
-      (line-minimum-distance prev-line line layout)))
+      (line-minimum-distance prev-line line layout ignore-padding)))
 
 ;;;
 ;;; Page breaking functions
@@ -124,7 +124,7 @@ is what have collected so far, and has ascending page numbers."
                                        inter-system-space))
        user)))
 
-(define (space-systems page-height lines ragged? paper)
+(define (space-systems page-height lines ragged paper ignore-padding)
   "Compute lines positions on page: return force and line positions as a pair.
  force is #f if lines do not fit on page."
   (let* ((empty-stencil (ly:make-stencil '() '(0 . 0) '(0 . 0)))
@@ -134,7 +134,7 @@ is what have collected so far, and has ascending page numbers."
                                (list empty-prob)
                                '())))
         (springs (map (lambda (prev-line line)
-                         (list (line-ideal-distance prev-line line paper)
+                         (list (line-ideal-distance prev-line line paper ignore-padding)
                                (/ 1.0 (line-next-space prev-line line paper))))
                        lines
                        cdr-lines))
@@ -142,7 +142,7 @@ is what have collected so far, and has ascending page numbers."
                       (lambda (prev-line line)
                         (set! i (1+ i))
                         (list i (1+ i)
-                              (line-minimum-distance prev-line line paper))))
+                              (line-minimum-distance prev-line line paper ignore-padding))))
                        lines
                        cdr-lines))
          (last-line (car (last-pair lines)))
@@ -154,27 +154,31 @@ is what have collected so far, and has ascending page numbers."
                            (- (interval-start (paper-system-extent
                                                last-line Y)))))
          (space-result
-          (ly:solve-spring-rod-problem springs rods space-to-fill ragged?)))
+          (ly:solve-spring-rod-problem springs rods space-to-fill ragged)))
     (cons (car space-result)
           (map (lambda (y)
                  (+ y topskip))
                (cdr space-result)))))
 
-(define (make-page-from-systems paper-book lines page-number ragged? last?)
+(define (make-page-from-systems paper-book lines page-number ragged last)
   (let*
     ((page (make-page
             paper-book
             'lines lines
             'page-number page-number
-            'is-last last?))
+            'is-last last))
      (height (page-printable-height page))
      (posns (if (> (length lines) 0)
-               (cdr (space-systems height lines ragged? (ly:paper-book-paper paper-book)))
+               (let* ((paper (ly:paper-book-paper paper-book))
+                      (spacing (space-systems height lines ragged paper #f)))
+                 (if (inf? (car spacing))
+                     (cdr (space-systems height lines ragged paper #t))
+                     (cdr spacing)))
                '())))
     (page-set-property! page 'configuration posns)
     page))
 
-(define (walk-paths done-lines best-paths current-lines last? current-best
+(define (walk-paths done-lines best-paths current-lines last current-best
                     paper-book page-alist)
   "Return the best optimal-page-break-node that contains
 CURRENT-LINES.  DONE-LINES.reversed ++ CURRENT-LINES is a consecutive
@@ -185,18 +189,18 @@ CURRENT-BEST is the best result sofar, or #f."
   (let* ((paper (ly:paper-book-paper paper-book))
          (this-page (make-page
                      paper-book
-                     'is-last last?
+                     'is-last last
                      'page-number (if (null? best-paths)
                                       (ly:output-def-lookup paper 'first-page-number)
                                       (1+ (page-page-number (first best-paths))))))
-         (ragged-all? (eq? #t (ly:output-def-lookup paper 'ragged-bottom)))
-         (ragged-last? (eq? #t (ly:output-def-lookup paper 'ragged-last-bottom)))
-         (ragged? (or ragged-all? (and ragged-last? last?)))
+         (ragged-all (eq? #t (ly:output-def-lookup paper 'ragged-bottom)))
+         (ragged-last (eq? #t (ly:output-def-lookup paper 'ragged-last-bottom)))
+         (ragged (or ragged-all (and ragged-last last)))
          (height (page-printable-height this-page))
-         (vertical-spacing (space-systems height current-lines ragged? paper))
+         (vertical-spacing (space-systems height current-lines ragged paper #f))
          (satisfied-constraints (car vertical-spacing))
          (force (if satisfied-constraints
-                    (if (and last? ragged-last?)
+                    (if (and last ragged-last)
                         0.0
                         satisfied-constraints)
                     10000))
@@ -234,7 +238,7 @@ CURRENT-BEST is the best result sofar, or #f."
          (list
           "\nuser pen " user-penalty
           "\nsatisfied-constraints" satisfied-constraints
-          "\nlast? " last? "ragged?" ragged?
+          "\nlast? " last "ragged?" ragged
           "\nis-better " is-better " total-penalty " total-penalty "\n"
           "\nconfig " positions
           "\nforce " force
@@ -250,7 +254,7 @@ CURRENT-BEST is the best result sofar, or #f."
              satisfied-constraints)
         (walk-paths (cdr done-lines) (cdr best-paths)
                     (cons (car done-lines) current-lines)
-                    last? new-best
+                    last new-best
                     paper-book page-alist)
         new-best)))
 
@@ -262,8 +266,8 @@ DONE."
   (if (null? todo)
       (car best-paths)
       (let* ((this-line (car todo))
-             (last? (null? (cdr todo)))
-             (next (walk-paths done best-paths (list this-line) last? #f
+             (last (null? (cdr todo)))
+             (next (walk-paths done best-paths (list this-line) last #f
                                paper-book page-alist)))
         (walk-lines (cons this-line done)
                     (cons next best-paths)