]> git.donarmstrong.com Git - lilypond.git/commitdiff
(fill_pages): New method. Try to cramp or
authorJan Nieuwenhuizen <janneke@gnu.org>
Fri, 12 Mar 2004 21:30:39 +0000 (21:30 +0000)
committerJan Nieuwenhuizen <janneke@gnu.org>
Fri, 12 Mar 2004 21:30:39 +0000 (21:30 +0000)
expand pages.

ChangeLog
input/test/title-markup.ly
lily/include/paper-book.hh
lily/paper-book.cc
lily/parser.yy
lily/stencil-scheme.cc

index b3316b63de355fc440f7a7ab7d141f32d0be111b..cb511a7d60e80d849406a6b55e6c236bd26bc03b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2004-03-12  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+       * lily/paper-book.cc (fill_pages): New method.  Try to cramp or
+       expand pages.
+
 2004-03-12  Han-Wen Nienhuys   <hanwen@xs4all.nl>
 
        * scm/part-combiner.scm (make-autochange-music): switch rests
index 5b5311b4031566a01aa711fb9e39fef2394173a0..a4ce65ff14a52d28e763a833d2991604c33c9c51 100644 (file)
@@ -78,7 +78,7 @@ spaceTest = \markup { "two space chars" }
 
 \score {
     \context Staff \notes \relative c' {
-       \repeat unfold 30 { a b c d \break }
+       \repeat unfold 35 { a b c d \break }
        c1
     }
 }
index 2e58a51388616c56a60c2f0cca0c7e57696e3740..8a250407333889f124d18d60005d65518d5b91d0 100644 (file)
@@ -23,9 +23,14 @@ public:
   Array<SCM> global_headers_;
   Link_array<Paper_def> papers_;
   Array<SCM> scores_;
+  Real height_;
+  Protected_scm copyright_;
+  Protected_scm tagline_;
 
   Paper_book ();
+  void init ();
   Link_array<Page> *get_pages ();
+  Link_array<Page> *fill_pages (Page*, int, Real);
   SCM get_scopes (int);
   Stencil* get_title (int);
   void output (String);
index 0fed5b78fb8b3c525da05c940dd53ce48f20f9a0..b89d0a86b6b06a2c3fc7b0ad31630256e0498786 100644 (file)
@@ -7,6 +7,7 @@
 */
 
 #include <stdio.h>
+#include <math.h>
 
 #include "ly-module.hh"
 #include "main.hh"
@@ -16,6 +17,9 @@
 #include "paper-score.hh"
 #include "stencil.hh"
 
+static Real const MIN_COVERAGE = 0.66;
+static Real const MAX_CRAMP = 0.05;
+
 static SCM
 stencil2line (Stencil* stil)
 {
@@ -121,6 +125,14 @@ Page::output (Paper_outputter *out, bool is_last)
   Offset o (left_margin_, top_margin_);
   Real vfill = line_count_ > 1 ? (text_height () - height_) / (line_count_ - 1)
     : 0;
+
+  Real coverage = height_ / text_height ();
+  if (coverage < MIN_COVERAGE)
+    /* Do not space out a badly filled page.  This is too simplistic
+       (ie broken), because this should not vary too much between
+       (subsequent?) pages in a book.  */
+    vfill = 0;
+
   if (get_header ())
     {
       out->output_line (stencil2line (get_header ()), &o, false);
@@ -138,8 +150,20 @@ Page::output (Paper_outputter *out, bool is_last)
       if (gh_pair_p (ly_cdr (s)) && ly_car (offset) != ly_symbol2scm ("title"))
        o[Y_AXIS] += vfill; 
     }
+
+#if 0
   if (get_copyright () || get_tagline () || get_footer ())
     o[Y_AXIS] += foot_sep_;
+#else
+  o[Y_AXIS] = vsize_ - bottom_margin_;
+  if (get_copyright ())
+    o[Y_AXIS] -= get_copyright ()->extent (Y_AXIS).length ();
+  if (get_tagline ())
+    o[Y_AXIS] -= get_tagline ()->extent (Y_AXIS).length ();
+  if (get_footer ())
+    o[Y_AXIS] -= get_footer ()->extent (Y_AXIS).length ();
+#endif
+
   if (get_copyright ())
     out->output_line (stencil2line (get_copyright ()), &o,
                      is_last && !get_tagline () && !get_footer ());
@@ -241,29 +265,26 @@ Paper_book::get_title (int i)
   return title;
 }
 
-/* Ideas:
-   - real page breaking algorithm (Gourlay?)
-   - override: # pages, or pageBreakLines= #'(3 3 4), ?  */
-Link_array<Page>*
-Paper_book::get_pages ()
+/* calculate book height, #lines, stencils.  */
+void
+Paper_book::init ()
 {
-  Link_array<Page> *pages = new Link_array<Page>;
   int score_count = scores_.size ();
 
   /* Calculate the full book height.  Hmm, can't we cache system
      heights while making stencils?  */
-  Real book_height = 0;
+  height_ = 0;
   for (int i = 0; i < score_count; i++)
     {
       Stencil *title = get_title (i);
       if (title)
-       book_height += title->extent (Y_AXIS).length ();
+       height_ += title->extent (Y_AXIS).length ();
 
       int line_count = SCM_VECTOR_LENGTH ((SCM) scores_[i]);
       for (int j = 0; j < line_count; j++)
        {
          SCM line = scm_vector_ref ((SCM) scores_[i], scm_int2num (j));
-         book_height += ly_scm2offset (ly_car (line))[Y_AXIS];
+         height_ += ly_scm2offset (ly_car (line))[Y_AXIS];
        }
     }
 
@@ -271,35 +292,104 @@ Paper_book::get_pages ()
   SCM scopes = get_scopes (0);
 
   SCM make_tagline = scm_primitive_eval (ly_symbol2scm ("make-tagline"));
-  SCM tagline = scm_call_2 (make_tagline, paper->smobbed_copy (), scopes);
+  tagline_ = scm_call_2 (make_tagline, paper->smobbed_copy (), scopes);
   Real tag_height = 0;
-  if (Stencil *s = unsmob_stencil (tagline))
+  if (Stencil *s = unsmob_stencil (tagline_))
     tag_height = s->extent (Y_AXIS).length ();
-  book_height += tag_height;
+  height_ += tag_height;
 
   SCM make_copyright = scm_primitive_eval (ly_symbol2scm ("make-copyright"));
-  SCM copyright = scm_call_2 (make_copyright, paper->smobbed_copy (), scopes);
+  copyright_ = scm_call_2 (make_copyright, paper->smobbed_copy (), scopes);
   Real copy_height = 0;
-  if (Stencil *s = unsmob_stencil (copyright))
+  if (Stencil *s = unsmob_stencil (copyright_))
     copy_height = s->extent (Y_AXIS).length ();
-  book_height += copy_height;
-  
+  height_ += copy_height;
+}
+
+/* Ideas:
+   - real page breaking algorithm (Gourlay?)
+     Hmmughr, Gourlay uses Grobs, columns etc -- looks like it needs serious
+     refactoring before it can be applied to Page breaking...
+   - override: # pages, or pageBreakLines= #'(3 3 4), ?  */
+Link_array<Page>*
+Paper_book::get_pages ()
+{
+  init ();
   Page::page_count_ = 0;
-  int page_number = 0;
-  Page *page = new Page (paper, ++page_number);
-  int page_count = int (book_height / page->text_height () + 0.5);
-  if (unsmob_stencil (copyright))
-    page->copyright_ = copyright;
-  if (unsmob_stencil (tagline) && page_number == page_count)
-    page->tagline_ = tagline;
+  Paper_def *paper = papers_[0];
+  Page *page = new Page (paper, 1);
+
+  Real text_height = page->text_height ();
+  Real page_frac = height_ / text_height;
+  int page_count = (int) ceil (page_frac);
+  if (unsmob_stencil (copyright_))
+    page->copyright_ = copyright_;
+  if (unsmob_stencil (tagline_) && page_count == 1)
+    page->tagline_ = tagline_;
+
+  /* Attempt to fill pages better using FUDGE kludge.  */
+  Real r = page_frac - (int) page_frac;
+  Real cramp_fudge = page_count > 1 ? (r / (page_count - 1)) * text_height : 0;
+  Real expand_fudge = - ((1 - r) / page_count) * text_height;
   
-#if 0  
-  fprintf (stderr, "book_height: %f\n", book_height);
-  fprintf (stderr, "vsize: %f\n", page->vsize_);
-  fprintf (stderr, "pages: %d\n", page_count);
-#endif
+  Link_array<Page>* pages = 0;
+  if ((page_count > 1 && (r / (page_count - 1)) < MAX_CRAMP))
+    {
+      /* Just a little more space (<MAX_CRAMP) per page is needed,
+        cramp onto one page less.  */
+      pages = fill_pages (page, page_count - 1, cramp_fudge);
+      if (pages->size () != page_count - 1)
+       {
+         /* Cramping failed.  */
+         page = pages->get (0);
+         delete pages;
+         pages = 0;
+       }
+    }      
+  if (!pages && ((1 - r) / page_count) < 1 - MIN_COVERAGE)
+    {
+      /* There is space left, but not so much that paged would have too
+        little blackness (< MIN_COVERAGE), distribute evenly.  */
+      pages = fill_pages (page, page_count, expand_fudge);
+      bool badly_covered = false;
+      if (pages->size () == page_count)
+       for (int i = 0; i < page_count; i++)
+         {
+           Page *p = (*pages)[i];
+           Real coverage = p ->height_ / p->text_height ();
+           if (coverage < MIN_COVERAGE)
+             {
+               badly_covered = true;
+               break;
+             }
+         }
+      if (pages->size () != page_count || badly_covered)
+       {
+         /* expanding failed.  */
+         page = pages->get (0);
+         delete pages;
+         pages = 0;
+       }
+    }
+  
+  if (!pages)
+    /* Fudging failed; just fill pages.  */
+    pages = fill_pages (page, page_count, 0);
+  return pages;
+}
 
-  /* Simplistic page breaking.  */
+/* Simplistic page breaking:
+   add lines until HEIGHT > PAGE.TEXT_HEIGHT_ + FUDGE  */
+Link_array<Page>*
+Paper_book::fill_pages (Page *page, int page_count, Real fudge)
+{
+  int page_number = 1;
+  int score_count = scores_.size ();
+  Paper_def *paper = papers_[0];
+  Link_array<Page> *pages = new Link_array<Page>;
+  page->lines_ = SCM_EOL;
+  page->height_ = 0;
+  page->line_count_ = 0;
   Real text_height = page->text_height ();
   for (int i = 0; i < score_count; i++)
     {
@@ -313,27 +403,33 @@ Paper_book::get_pages ()
        {
          SCM line = scm_vector_ref ((SCM) scores_[i], scm_int2num (j));
          h += ly_scm2offset (ly_car (line))[Y_AXIS];
-         if (page->height_ + h > text_height)
+         Real fill = (page->height_ - text_height) / text_height;
+         // Real fill_h = (page->height_ + h - text_height) / text_height;
+         Real fudged_fill = (page->height_ - (text_height + fudge))
+           / (text_height + fudge);
+         Real fudged_fill_h = ((page->height_ + h) - (text_height + fudge))
+           / (text_height + fudge);
+         if (fill > -MAX_CRAMP
+             || (fudged_fill > -MAX_CRAMP
+                 && (fudge < 0
+                     || !(fudged_fill_h > 0
+                          && abs (fudged_fill_h) < 4 * abs (fudged_fill)))))
            {
              pages->push (page);
              page = new Page (paper, ++page_number);
-             if (unsmob_stencil (tagline) && page_number == page_count)
-               page->tagline_ = tagline;
+             if (unsmob_stencil (tagline_) && page_number == page_count)
+               page->tagline_ = tagline_;
              text_height = page->text_height ();
            }
-         if (page->height_ + h <= text_height || page->height_ == 0)
-           {
-             if (j == 0 && title)
-               page->lines_
-                 = ly_snoc (title2line (title), page->lines_);
-             page->lines_ = ly_snoc (line, page->lines_);
-             page->line_count_++;
-             page->height_ += h;
-             h = 0;
-           }
+         if (j == 0 && title)
+           page->lines_ = ly_snoc (title2line (title), page->lines_);
+         page->lines_ = ly_snoc (line, page->lines_);
+         page->line_count_++;
+         page->height_ += h;
+         h = 0;
        }
     }
-  
+
   pages->push (page);
   return pages;
 }
index 17adedcc94d35f499ae666ff4eae8f7264c5014c..ef4ee306327af2ba0631b00e3f12cc6c4e54945f 100644 (file)
@@ -457,7 +457,6 @@ toplevel_expression:
                   id = id ? id->clone () : new Paper_def;
        
                   default_rendering (sc->music_, id->self_scm (), head, outname);
-
                   scm_gc_unprotect_object (id->self_scm ());
                }
                scm_gc_unprotect_object (sc->self_scm ());
index 4e30e129aea4b8049284bee7de98a3c654bd6cc5..0f859d822758644aee75b14486685bfd3c789e8e 100644 (file)
@@ -16,7 +16,7 @@
   UMGH. junkme!
   
  */
-LY_DEFINE (ly_stencil_set_extent_x,"ly:stencil-set-extent!",
+LY_DEFINE (ly_stencil_set_extent_x, "ly:stencil-set-extent!",
           3, 0, 0, (SCM stil, SCM axis, SCM np),
           "Set the extent of @var{stil} "
           "(@var{extent} must be a pair of numbers) "
@@ -49,7 +49,7 @@ LY_DEFINE (ly_translate_stencil_axis, "ly:stencil-translate-axis",
 
 }
 
-LY_DEFINE (ly_translate_stencil,"ly:stencil-translate",
+LY_DEFINE (ly_translate_stencil, "ly:stencil-translate",
           2, 0, 0, (SCM stil, SCM offset),
           "Return a @var{stil}, "
           "but translated by @var{offset} (a pair of numbers).")
@@ -66,7 +66,7 @@ LY_DEFINE (ly_translate_stencil,"ly:stencil-translate",
 }
 
 LY_DEFINE (ly_stencil_get_expr, "ly:stencil-get-expr",
-          1 , 0, 0, (SCM stil),
+          1, 0, 0, (SCM stil),
           "Return the expression of @var{stil}.")
 {
   Stencil *s = unsmob_stencil (stil);
@@ -74,8 +74,8 @@ LY_DEFINE (ly_stencil_get_expr, "ly:stencil-get-expr",
   return s->get_expr ();
 }
 
-LY_DEFINE (ly_stencil_get_extent,
-          "ly:stencil-extent", 2 , 0, 0,  (SCM stil, SCM axis),
+LY_DEFINE (ly_stencil_get_extent, "ly:stencil-extent",
+          2, 0, 0, (SCM stil, SCM axis),
           "Return a pair of numbers signifying the extent of @var{stil} in "
           "@var{axis} direction (0 or 1 for x and y axis respectively).")
 {
@@ -87,10 +87,8 @@ LY_DEFINE (ly_stencil_get_extent,
 }
 
 LY_DEFINE (ly_stencil_moved_to_edge, "ly:stencil-moved-to-edge",
-          4, 2, 0,  (SCM first, SCM axis, SCM direction,
-                     SCM second,
-                     SCM padding,
-                     SCM minimum),
+          4, 2, 0, (SCM first, SCM axis, SCM direction, SCM second,
+                    SCM padding, SCM minimum),
           "Similar to @code{ly:stencil-combine-edge}, but returns "
           "@var{second} positioned to be next to @var{first}. ")
 {
@@ -171,8 +169,8 @@ LY_DEFINE (ly_stencil_combine_at_edge, "ly:stencil-combine-at-edge",
   return result.smobbed_copy ();
 }
 
-LY_DEFINE (ly_stencil_add ,
-          "ly:stencil-add", 0, 0, 1, (SCM args),
+LY_DEFINE (ly_stencil_add , "ly:stencil-add",
+          0, 0, 1, (SCM args),
           "Combine stencils. Takes any number of arguments.")
 {
 #define FUNC_NAME __FUNCTION__
@@ -193,8 +191,8 @@ LY_DEFINE (ly_stencil_add ,
   return result.smobbed_copy ();
 }
 
-LY_DEFINE (ly_make_stencil,
-          "ly:make-stencil", 3, 0, 0,  (SCM expr, SCM xext, SCM yext),
+LY_DEFINE (ly_make_stencil, "ly:make-stencil",
+          3, 0, 0,  (SCM expr, SCM xext, SCM yext),
           " \n"
           "Stencils are a device independent output expressions."
           "They carry two pieces of information: \n\n"
@@ -221,8 +219,8 @@ fontify_atom (Font_metric const *met, SCM f)
                        ly_quote_scm (met->description_), f, SCM_UNDEFINED);
 }
 
-LY_DEFINE (ly_fontify_atom,"ly:fontify-atom", 2, 0, 0,
-          (SCM met, SCM f),
+LY_DEFINE (ly_fontify_atom,"ly:fontify-atom",
+          2, 0, 0, (SCM met, SCM f),
           "Add a font selection command for the font metric @var{met} "
           "to @var{f}.")
 {