]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/line-of-score.cc
release: 1.3.62
[lilypond.git] / lily / line-of-score.cc
index 5ca3685dee659a8643a3728510773252a9dc255d..62bd6a153d0b2ac5acc8711f8c0bb1f6a5b39441 100644 (file)
 #include "string.hh"
 #include "warn.hh"
 #include "dimensions.hh"
+#include "molecule.hh"
+#include "all-font-metrics.hh"
 
 Line_of_score::Line_of_score()
+  : Spanner (SCM_EOL)
 {
-  set_elt_property ("columns", SCM_EOL);
-  set_elt_property ("all-elements", SCM_EOL);
+  set_elt_pointer ("columns", SCM_EOL);
+  set_elt_pointer ("all-elements", SCM_EOL);
 
   Axis_group_interface (this).set_interface ();
   Axis_group_interface (this).set_axes (Y_AXIS,X_AXIS);
 }
 
-/*
-  Ugh.  this is grossly hairy.
- */
+int
+Line_of_score::element_count () const
+{
+  return scm_ilength ( get_elt_pointer ("all-elements"));
+}
 
 void
 Line_of_score::typeset_element (Score_element * elem_p)
 {
   elem_p->pscore_l_ = pscore_l_;
-  Group_interface (this, "all-elements").add_element (elem_p);
+  Pointer_group_interface (this, "all-elements").add_element (elem_p);
   scm_unprotect_object (elem_p->self_scm_);
 }
 
-SCM
+void
 Line_of_score::output_lines ()
 {
-  for (SCM s = get_elt_property ("all-elements");
+  for (SCM s = get_elt_pointer ("all-elements");
        gh_pair_p (s); s = gh_cdr (s))
     {
       unsmob_element (gh_car (s))->do_break_processing ();
     }
-
   /*
-    fixups must be done in broken line_of_scores, because new elements are put over there. 
-   */
+    fixups must be done in broken line_of_scores, because new elements
+    are put over there.  */
+  int count = 0;
   for (int i=0; i < broken_into_l_arr_.size (); i++)
     {
       Score_element *se = broken_into_l_arr_[i];
-
-      for (SCM s = se->get_elt_property ("all-elements");
-          gh_pair_p (s); s = gh_cdr (s))
+      SCM all = se->get_elt_pointer ("all-elements");
+      for (SCM s = all; gh_pair_p (s); s = gh_cdr (s))
        {
          unsmob_element (gh_car (s))->fixup_refpoint ();
        }
+      count += scm_ilength (all);
     }
+
   
   /*
     needed for doing items.
    */
-  for (SCM s = get_elt_property ("all-elements");
+  for (SCM s = get_elt_pointer ("all-elements");
        gh_pair_p (s); s = gh_cdr (s))
     {
       unsmob_element (gh_car (s))->fixup_refpoint ();
     }
   
-  for (SCM s = get_elt_property ("all-elements");
+  for (SCM s = get_elt_pointer ("all-elements");
        gh_pair_p (s); s = gh_cdr (s))
     {
       unsmob_element (gh_car (s))->handle_broken_dependencies ();
     }
   handle_broken_dependencies ();
+
+  if (verbose_global_b)
+    progress_indication ( _f("Element count %d.",  count + element_count()));
+
   
   for (int i=0; i < broken_into_l_arr_.size (); i++)
     {
       Line_of_score *line_l = dynamic_cast<Line_of_score*> (broken_into_l_arr_[i]);
 
-      progress_indication ("[");
+      if (verbose_global_b)
+       progress_indication ("[");
       line_l->post_processing ();
-      progress_indication (to_str (i));
-      progress_indication ("]");
-    }
 
-  SCM list = SCM_EOL; 
-  for (int i=broken_into_l_arr_.size (); i--;)
-    {
-      Line_of_score * l =  dynamic_cast<Line_of_score*> (broken_into_l_arr_[i]);
-      list = gh_cons (gh_cdr (l->output_), list);
+      if (verbose_global_b)
+       {
+         progress_indication (to_str (i));
+         progress_indication ("]");
+       }
     }
-  return list;
 }
 
 // const?
@@ -146,48 +153,35 @@ enter:
     }
   else
     {
-      output_scheme (gh_list (ly_symbol2scm ("placebox"),
-                             gh_double2scm (o[X_AXIS]),
-                             gh_double2scm (o[Y_AXIS]),
-                             expr,
-                             SCM_UNDEFINED));
+      pscore_l_->outputter_l_->
+       output_scheme (gh_list (ly_symbol2scm ("placebox"),
+                               gh_double2scm (o[X_AXIS]),
+                               gh_double2scm (o[Y_AXIS]),
+                               expr,
+                               SCM_UNDEFINED));
     }
 }
 
 void
 Line_of_score::output_scheme (SCM s)
 {
-  gh_set_cdr_x (output_, gh_cons (s, gh_cdr (output_)));
+  pscore_l_->outputter_l_->output_scheme (s);
 }
 
 void
 Line_of_score::add_column (Paper_column*p)
 {
-  SCM cs = get_elt_property ("columns");
+  SCM cs = get_elt_pointer ("columns");
   Score_element * prev =  gh_pair_p (cs) ? unsmob_element (gh_car (cs)) : 0;
   int rank = prev ? dynamic_cast<Paper_column*> (prev)->rank_i () + 1 : 0; 
 
   p->set_rank (rank);
-  set_elt_property ("columns",  gh_cons (p->self_scm_, cs));
+  set_elt_pointer ("columns",  gh_cons (p->self_scm_, cs));
 
   Axis_group_interface (this).add_element (p);
   typeset_element (p);
 }
 
-Link_array<Paper_column>
-Line_of_score::column_l_arr ()const
-{
-  return Group_interface__extract_elements (this,
-                                           (Paper_column*) 0, "columns");
-
-}
-
-int
-Line_of_score::compare (Line_of_score* const &p1,Line_of_score* const &p2)
-{
-  return p1->rank_i_ - p2->rank_i_;
-}
-
 
 void
 fixup_refpoints (SCM s)
@@ -210,32 +204,38 @@ fixup_refpoints (SCM s)
 void
 Line_of_score::pre_processing ()
 {
-  for (SCM s = get_elt_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s))
-    unsmob_element (gh_car (s))->do_breakable_col_processing ();
-  for (SCM s = get_elt_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s))
+  for (SCM s = get_elt_pointer ("all-elements"); gh_pair_p (s); s = gh_cdr (s))
+    unsmob_element (gh_car (s))->discretionary_processing ();
+
+  if(verbose_global_b)
+    progress_indication ( _f("Element count %d ",  element_count ()));
+
+  
+  for (SCM s = get_elt_pointer ("all-elements"); gh_pair_p (s); s = gh_cdr (s))
     unsmob_element (gh_car (s))->handle_prebroken_dependencies ();
   
-  fixup_refpoints (get_elt_property ("all-elements"));
+  fixup_refpoints (get_elt_pointer ("all-elements"));
   
-  for (SCM s = get_elt_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s))
+  for (SCM s = get_elt_pointer ("all-elements"); gh_pair_p (s); s = gh_cdr (s))
     {
       Score_element* sc = unsmob_element (gh_car (s));
-      sc->calculate_dependencies (PRECALCED, PRECALCING, &Score_element::before_line_breaking);
+      sc->calculate_dependencies (PRECALCED, PRECALCING, ly_symbol2scm ("before-line-breaking-callback"));
     }
   
   progress_indication ("\n" + _ ("Calculating column positions...") + " " );
-  for (SCM s = get_elt_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s))
+  for (SCM s = get_elt_pointer ("all-elements"); gh_pair_p (s); s = gh_cdr (s))
     unsmob_element (gh_car (s))->do_space_processing ();
 }
 
 void
 Line_of_score::post_processing ()
 {
-  for (SCM s = get_elt_property ("all-elements");
+  for (SCM s = get_elt_pointer ("all-elements");
        gh_pair_p (s); s = gh_cdr (s))
     {
       Score_element* sc = unsmob_element (gh_car (s));
-      sc->calculate_dependencies (POSTCALCED, POSTCALCING, &Score_element::after_line_breaking);
+      sc->calculate_dependencies (POSTCALCED, POSTCALCING,
+                                 ly_symbol2scm ("after-line-breaking-callback"));
     }
 
   Interval i(extent(Y_AXIS));
@@ -251,21 +251,54 @@ Line_of_score::post_processing ()
       height = 50 CM;
     }
 
-  output_ = gh_cons (SCM_EOL, SCM_EOL);
-  output_scheme (gh_list (ly_symbol2scm ("stop-line"), SCM_UNDEFINED));
-  for (SCM s = get_elt_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s))
-    unsmob_element (gh_car (s))->output_processing ();
+  /*
+    generate all molecules  to trigger all font loads.
+
+    (ugh. This is not very memory efficient.)  */
+  for (SCM s = get_elt_pointer ("all-elements"); gh_pair_p (s); s = gh_cdr (s))
+    unsmob_element (gh_car (s))->get_molecule ();
+  
+  /*
+    font defs;
+   */
+  SCM font_names = ly_quote_scm (all_fonts_global_p->font_descriptions ());  
+  output_scheme (gh_list (ly_symbol2scm ("define-fonts"),
+                                       font_names,
+                                       SCM_UNDEFINED));
+
+  /*
+    line preamble.
+   */
   output_scheme (gh_list (ly_symbol2scm ("start-line"),
                          gh_double2scm (height),
                          SCM_UNDEFINED));
-}
+  
+  Real il = paper_l ()->get_var ("interline");
 
-void
-Line_of_score::output_all () 
-{
-  calculate_dependencies (BREWED, BREWING, &Score_element::output_processing);
+  /*
+    all elements.
+   */ 
+  for (SCM s = get_elt_pointer ("all-elements"); gh_pair_p (s); s = gh_cdr (s))
+    {
+      Score_element * sc =  unsmob_element (gh_car (s));
+      Molecule m = sc->get_molecule ();
+      
+      Offset o (sc->relative_coordinate (this, X_AXIS),
+               sc->relative_coordinate (this, Y_AXIS));
+
+      SCM e = sc->get_elt_property ("extra-offset");
+      if (gh_pair_p (e))
+       {
+         o[X_AXIS] += il * gh_scm2double (gh_car (e));
+         o[Y_AXIS] += il * gh_scm2double (gh_cdr (e));      
+       }
+
+      output_molecule (m.get_expr (), o);
+    }
+  output_scheme (gh_list (ly_symbol2scm ("stop-line"), SCM_UNDEFINED));
 }
 
+
 Link_array<Item> 
 Line_of_score::broken_col_range (Item const*l, Item const*r) const
 {
@@ -273,15 +306,15 @@ Line_of_score::broken_col_range (Item const*l, Item const*r) const
 
   l = l->column_l ();
   r = r->column_l ();
-  SCM s = get_elt_property ("columns");
+  SCM s = get_elt_pointer ("columns");
 
-  while (gh_car (s) != r->self_scm_)
+  while (gh_pair_p (s) && gh_car (s) != r->self_scm_)
     s = gh_cdr  (s);
     
-
-  s = gh_cdr (s);
+  if (gh_pair_p (s))
+    s = gh_cdr (s);
   
-  while (gh_car (s) != l->self_scm_)
+  while (gh_pair_p (s) && gh_car (s) != l->self_scm_)
     {
       Paper_column *c
        = dynamic_cast<Paper_column*> (unsmob_element (gh_car (s)));
@@ -295,5 +328,28 @@ Line_of_score::broken_col_range (Item const*l, Item const*r) const
   return ret;
 }
 
-
-
+/**
+   Return all columns, but filter out any unused columns , since they might
+   disrupt the spacing problem.
+ */
+Link_array<Paper_column>
+Line_of_score::column_l_arr ()const
+{
+  Link_array<Paper_column> acs
+    = Pointer_group_interface__extract_elements (this, (Paper_column*) 0, "columns");
+  bool bfound = false;
+  for (int i= acs.size (); i -- ; )
+    {
+      bool brb = acs[i]->breakable_b();
+      bfound = bfound || brb;
+
+      /*
+       the last column should be breakable. Weed out any columns that
+       seem empty. We need to retain breakable columns, in case
+       someone forced a breakpoint.
+      */
+      if (!bfound || !acs[i]->used_b ())
+       acs.del (i);
+    }
+  return acs;
+}