]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/break-alignment-interface.cc
Run `make grand-replace'.
[lilypond.git] / lily / break-alignment-interface.cc
index 7b19d75fdc33eeff6b1ebadf7cdb04e661773b6f..fdf0afb58aae1822d83ad204512694c71c2956fe 100644 (file)
@@ -3,7 +3,7 @@
 
   source file of the GNU LilyPond music typesetter
 
-  (c) 1997--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
+  (c) 1997--2008 Han-Wen Nienhuys <hanwen@xs4all.nl>
 */
 
 
@@ -86,13 +86,16 @@ Break_alignment_interface::add_element (Grob *me, Grob *toadd)
   Align_interface::add_element (me, toadd);
 }
 
-MAKE_SCHEME_CALLBACK(Break_alignment_interface, calc_positioning_done, 1)
+MAKE_SCHEME_CALLBACK (Break_alignment_interface, calc_positioning_done, 1)
 SCM
 Break_alignment_interface::calc_positioning_done (SCM smob)
 {
   Grob *grob = unsmob_grob (smob);  
   Item *me = dynamic_cast<Item *> (grob);
 
+
+  me->set_property ("positioning-done", SCM_BOOL_T);
+
   vector<Grob*> elems = ordered_elements (me);
   vector<Interval> extents;
 
@@ -217,7 +220,7 @@ Break_alignment_interface::calc_positioning_done (SCM smob)
       else
        {
          extra_right_space = distance;
-         if (idx < offsets.size() - 1)
+         if (idx + 1 < offsets.size ())
            offsets[idx+1] = extents[idx][RIGHT] + distance;
        }
 
@@ -256,7 +259,7 @@ Break_alignment_interface::calc_positioning_done (SCM smob)
 
 
 
-MAKE_SCHEME_CALLBACK(Break_alignable_interface, self_align_callback, 1)
+MAKE_SCHEME_CALLBACK (Break_alignable_interface, self_align_callback, 1)
 SCM
 Break_alignable_interface::self_align_callback (SCM grob)
 {
@@ -265,81 +268,149 @@ Break_alignable_interface::self_align_callback (SCM grob)
   if (!Break_alignment_interface::has_interface (alignment))
     return scm_from_int (0);
 
-  SCM my_align = me->get_property ("break-align-symbol");
-  SCM order = Break_alignment_interface::break_align_order (alignment);
-
+  SCM symbol_list = me->get_property ("break-align-symbols");
   vector<Grob*> elements = Break_alignment_interface::ordered_elements (alignment);
   if (elements.size () == 0)
     return scm_from_int (0);
   
-  int last_idx_found = -1;
-  vsize i = 0;
-  for (SCM s = order; scm_is_pair (s); s = scm_cdr (s))  
+  int break_aligned_grob = -1;
+  for (; scm_is_pair (symbol_list); symbol_list = scm_cdr (symbol_list))
     {
-      if (i < elements.size ()
-         && elements[i]->get_property ("break-align-symbol") == scm_car (s))
+      SCM sym = scm_car (symbol_list);
+      for (vsize i = 0; i < elements.size (); i++)
        {
-         last_idx_found = i;
-         i ++;
+         if (elements[i]->get_property ("break-align-symbol") == sym)
+           {
+             if (Item::break_visible (elements[i])
+                 && !elements[i]->extent (elements[i], X_AXIS).is_empty ())
+               {
+                 break_aligned_grob = i;
+                 goto found_break_aligned_grob; /* ugh. need to break out of 2 loops */
+               }
+             else if (break_aligned_grob == -1)
+               break_aligned_grob = i;
+           }
        }
+    }
 
-      if (scm_car (s) == my_align)
-       break ;
-    }  
+found_break_aligned_grob:
+  if (break_aligned_grob == -1)
+    return scm_from_int (0);
 
-  Direction which_edge = LEFT;
-  if (vsize (last_idx_found + 1) < elements.size())
-    last_idx_found ++;
-  else
-    which_edge = RIGHT;
-  
-  Grob *common = me->common_refpoint (elements[last_idx_found], X_AXIS);
+  Grob *alignment_parent = elements[break_aligned_grob];
+  Grob *common = me->common_refpoint (alignment_parent, X_AXIS);
+  Real anchor = robust_scm2double (alignment_parent->get_property ("break-align-anchor"), 0);
 
-  return scm_from_double (robust_relative_extent (elements[last_idx_found], common, X_AXIS)[which_edge]
-                         - me->relative_coordinate (common, X_AXIS));
+  return scm_from_double (alignment_parent->relative_coordinate (common, X_AXIS)
+                         - me->relative_coordinate (common, X_AXIS)
+                         + anchor);
 }
 
-ADD_INTERFACE (Break_alignable_interface,
-              "Object that is aligned on a break aligment. ",
+MAKE_SCHEME_CALLBACK (Break_aligned_interface, calc_average_anchor, 1)
+SCM
+Break_aligned_interface::calc_average_anchor (SCM grob)
+{
+  Grob *me = unsmob_grob (grob);
+  Real avg = 0.0;
+  int count = 0;
 
-              /* properties */
-              "break-align-symbol "
-              )
+  /* average the anchors of those children that have it set */
+  extract_grob_set (me, "elements", elts);
+  for (vsize i = 0; i < elts.size (); i++)
+    {
+      SCM anchor = elts[i]->get_property ("break-align-anchor");
+      if (scm_is_number (anchor))
+       {
+         count++;
+         avg += scm_to_double (anchor);
+       }
+    }
 
+  return scm_from_double (count > 0 ? avg / count : 0);
+}
 
+MAKE_SCHEME_CALLBACK (Break_aligned_interface, calc_extent_aligned_anchor, 1)
+SCM
+Break_aligned_interface::calc_extent_aligned_anchor (SCM smob)
+{
+  Grob *me = unsmob_grob (smob);
+  Real alignment = robust_scm2double (me->get_property ("break-align-anchor-alignment"), 0.0);
+  Interval iv = me->extent (me, X_AXIS);
+
+  if (isinf (iv[LEFT]) && isinf (iv[RIGHT])) /* avoid NaN */
+    return scm_from_double (0.0);
+
+  return scm_from_double (iv.linear_combination (alignment));
+}
+
+MAKE_SCHEME_CALLBACK (Break_aligned_interface, calc_break_visibility, 1)
+SCM
+Break_aligned_interface::calc_break_visibility (SCM smob)
+{
+  /* a BreakAlignGroup is break-visible iff it has one element that is break-visible */
+  Grob *me = unsmob_grob (smob);
+  SCM ret = scm_c_make_vector (3, SCM_EOL);
+  extract_grob_set (me, "elements", elts);
+  for (int dir = 0; dir <= 2; dir++)
+    {
+      bool visible = false;
+      for (vsize i = 0; i < elts.size (); i++)
+       {
+         SCM vis = elts[i]->get_property ("break-visibility");
+         if (scm_is_vector (vis) && to_boolean (scm_c_vector_ref (vis, dir)))
+           visible = true;
+       }
+      scm_c_vector_set_x (ret, dir, scm_from_bool (visible));
+    }
+  return ret;
+}
+
+ADD_INTERFACE (Break_alignable_interface,
+              "Object that is aligned on a break aligment.",
+
+              /* properties */
+              "break-align-symbols "
+              );
 
 ADD_INTERFACE (Break_aligned_interface,
               "Items that are aligned in prefatory matter.\n"
               "\n"
-              "The spacing of these items is controlled by the @code{space-alist}\n"
-              "property. It contains a list @code{break-align-symbol}s with a specification\n"
-              "of the associated space. The space specification can be "
+              "The spacing of these items is controlled by the"
+              " @code{space-alist} property.  It contains a list"
+              " @code{break-align-symbol}s with a specification of the"
+              " associated space.  The space specification can be\n"
+              "\n"
               "@table @code\n"
               "@item (minimum-space . @var{spc}))\n"
-              "  Pad space until the distance is @var{spc}\n"
+              "Pad space until the distance is @var{spc}.\n"
               "@item (fixed-space . @var{spc})\n"
-              "  Set a fixed space\n"
+              "Set a fixed space.\n"
               "@item (semi-fixed-space . @var{spc})\n"
-              "  Set a space. Half of it is fixed and half is stretchable. \n"
-              "(does not work at start of line. fixme)\n"
+              "Set a space.  Half of it is fixed and half is stretchable."
+              " (does not work at start of line. fixme)\n"
               "@item (extra-space . @var{spc})\n"
-              "  Add @var{spc} amount of space.\n"
+              "Add @var{spc} amount of space.\n"
               "@end table\n"
               "\n"
-              "Special keys for the alist are @code{first-note} and @code{next-note}, signifying\n"
-              "the first note on a line, and the next note halfway a line.\n"
+              "Special keys for the alist are @code{first-note} and"
+              " @code{next-note}, signifying the first note on a line, and"
+              " the next note halfway a line.\n"
               "\n"
-              "Rules for this spacing are much more complicated than this. \n"
-              "See [Wanske] page 126 -- 134, [Ross] pg 143 -- 147\n",
+              "Rules for this spacing are much more complicated than this."
+              "  See [Wanske] page 126--134, [Ross] page 143--147.",
 
               /* properties */ 
+              "break-align-anchor "
+              "break-align-anchor-alignment "
               "break-align-symbol "
               "space-alist "
               );
 
 ADD_INTERFACE (Break_alignment_interface,
-              "The object that performs break aligment. See @ref{break-aligned-interface}.",
+              "The object that performs break aligment.  See"
+              " @ref{break-aligned-interface}.",
 
               /* properties */
               "positioning-done "
-              "break-align-orders");
+              "break-align-orders "
+              );