gnu-music-discuss
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Bars


From: Juergen Reuter
Subject: Re: Bars
Date: Fri, 08 Jun 2001 10:14:58 +0200

Han-Wen wrote on Tue, 1 May 2001:

> > +
> > +  // first walk: compute axis_group parent via common_refpoint () on all 
> > bars
> > +  Grob *refpoint = 0;
>
> init this with me, the translation of the me grob should be
> filtered. this also removes the need for checking below.

Ok.


> > +  /* assert: refpoint is an axis-group object */
>
> Incorrect. The refpoint may be any grob.

Hmh.  When I look at Axis_group_interface::group_extent_callback
(which is a very similar piece of code), the code suggests me, that
refpoint is assumed to be an axis-group object.  There, you at least
implicitly assume that the refpoint contains a grob property called
"elements".  Is that property defined for all grobs?


> > +  // compute extent of axis_group
> > +  Real last_staff_bar_length;
> > +  Real *interstaff_bar_length = new Real[staff_bar_count];
>
> I prefer that an Array<Real> be used.

Ok.

> > +   interstaff_bar_molecule[staff_bar_count] =
> > +     *unsmob_molecule (smobbed_interstaff_bar_molecule);
>
> don't do this -- you're storing a molecule on the heap, hiding it from
> GUILE GC.  This code is bound to crash in ugly ways.

interstaff_bar_molecule is just a local temporary variable for partial
molecules; they are finally collected in span_bar_molecule.  So this
should not be a problem, right?

> I think you're code is on the lengthy side, and the above points must
> be addressed before I consider putting the patch in. The code
> shouldn't have to be so difficult. Roughly, it should be like:
>
>   Grob * last_bar = 0;
>   for (SCM s = elements ; gh_pair (s) ; s =gh_cdr (s))
>     {
>       Grob *m = unsmob_grob (gh_car (s))
>
>
>       if (last_bar){
>           Interval l; l[LEFT] = last_bar->extent (refp, y_axis)[DOWN]
>           l[RIGHT] = m->extent (refp, y_axis)[UP]
>           span_bar_mol.add (make_bar_molecule (l));
>       }
>       last_bar = m;
>     }
>
>   return span_bar_mol;

Nope.  It is definitely *not* that simple.  First of all, you have to
compute refp (which you are silently using, but not defining).
Secondly, all molecules created by make_bar_molecule must be shifted
upwards by half the height of the whole axis group (otherwise they are
centered around the middle of the axis group); thirdly they all must
be shifted downwards by the sum of all staff_bars and interstaff_bars
that have been processed so far (otherwise they are aligned on a
single horizontal line).  And, finally, make_bar_molecule also has to
do some tiny things.

Calculating the height of the whole axis group itself can not be done
via refp->extent, since this would also consider lyrics below the
lowermost staff line and above the uppermost staff line.  However,
such lyrics should not have any affect on the alignment of the
interstaff bars.

All in all, after doing a complete rewrite of my patch based on your
suggestions, my revised patch is now 80 lines long (as compared to the
previously 100 lines).  The patch is against 1.4.2.

Another issue is, that my patch currently works with StaffGroup, but
not with ChoirStaff.  I assume this is because in ChoirStaff, there is
(as far as I understand) only a single bar line drawn that covers all
staff lines, while in StaffGroup, there is a bar line drawn for each
staff line.  As a solution, I would like to suggest, that, by default,
StaffGroup only engraves staff bars (just as is), and ChoirStaff, by
default, engraves staff bars (one per staff line, like StaffGroup)
plus interstaff bars.  I think, this would be a clean solution.

Greetings,
            Juergen

###############################################################################

--- grob-description.scm.orig   Thu May 17 11:40:11 2001
+++ grob-description.scm        Mon Jun  4 00:34:19 2001
@@ -518,7 +518,7 @@
        (SpanBar . (
                (break-align-symbol . Staff_bar)
                (bar-size-procedure . ,Span_bar::get_bar_size) 
-               (molecule-callback . ,Bar::brew_molecule)
+               (molecule-callback . ,Span_bar::brew_molecule)
                (visibility-lambda . ,begin-of-line-invisible)
                (X-extent-callback . ,Span_bar::width_callback)
                (Y-offset-callbacks . (,Span_bar::center_on_spanned_callback))

###############################################################################

--- span-bar.cc.orig    Sun Mar 11 19:10:34 2001
+++ span-bar.cc Fri Jun  8 02:50:25 2001
@@ -25,6 +25,107 @@
   me->add_dependency (b);
 }
 
+MAKE_SCHEME_CALLBACK (Span_bar,brew_molecule,1);
+
+/**
+ * Limitations/Bugs:
+ *
+ * (1) Elements from 'me->get_grob_property ("elements")' must be
+ * ordered according to their y coordinates relative to their common
+ * axis group parent.  Otherwise, the computation goes mad.  (TODO:
+ * apply a sort algorithm that ensures this precondition.)  However,
+ * until now, I have seen no case where lily has not fulfilled this
+ * precondition.
+ *
+ * (2) This method depends on bar_engraver not being removed from
+ * staff context.  If bar_engraver is removed, the size of the staff
+ * lines is evaluated as 0, which results in a solid span bar line
+ * with faulty y coordinate.
+ */
+SCM
+Span_bar::brew_molecule (SCM smobbed_me) 
+{
+  Grob *me = unsmob_grob (smobbed_me);
+  SCM first_elt = me->get_grob_property ("elements");
+  Grob *first_staff_bar = unsmob_grob (gh_car (first_elt));
+  Grob *last_staff_bar = 0;
+
+  // compute common refpoint of elements & last_staff_bar
+  Grob *refp = me;
+  for (SCM elts = first_elt;
+       gh_pair_p (elts);
+       elts = gh_cdr (elts))
+  {
+    SCM smobbed_staff_bar = gh_car (elts);
+    Grob *staff_bar = unsmob_grob (smobbed_staff_bar);
+    refp = staff_bar->common_refpoint (refp, Y_AXIS);
+    last_staff_bar = staff_bar;
+  }
+
+  // determine refp->extent, but ignore lyrics etc. above and below
+  Interval refp_extent;
+  refp_extent[LEFT] =
+    first_staff_bar->relative_coordinate (refp, (Axis)Y_AXIS) -
+    0.5 * (first_staff_bar->extent (refp, Y_AXIS)[UP] -
+          first_staff_bar->extent (refp, Y_AXIS)[DOWN]);
+  refp_extent[RIGHT] =
+    last_staff_bar->relative_coordinate (refp, (Axis)Y_AXIS) +
+    0.5 * (last_staff_bar->extent (refp, Y_AXIS)[UP] -
+          last_staff_bar->extent (refp, Y_AXIS)[DOWN]);
+
+  // global yoffs correction (compensate centering around refp)
+  Real yoffs = 0.5 * (refp_extent[LEFT] - refp_extent[RIGHT]);
+
+  // evaluate glyph
+  Span_bar::evaluate_glyph(me);
+  SCM glyph = me->get_grob_property (ly_symbol2scm ("glyph"));
+  String glyph_str = ly_scm2string (glyph);
+
+  // compose span_bar_mol
+  Molecule span_bar_mol = Molecule::Molecule ();
+  Grob *prev_staff_bar = 0;
+  Real prev_staff_bar_length = 0.0;
+  for (SCM elts = first_elt;
+       gh_pair_p (elts);
+       elts = gh_cdr (elts))
+  {
+    SCM smobbed_staff_bar = gh_car (elts);
+    SCM smobbed_staff_bar_molecule =
+      Bar::brew_molecule (smobbed_staff_bar);
+    Grob *staff_bar = unsmob_grob (smobbed_staff_bar);
+    Real staff_bar_length =
+      unsmob_molecule (smobbed_staff_bar_molecule)->
+      extent (Y_AXIS).length ();
+
+    if (prev_staff_bar) {
+
+      Interval l;
+      l[LEFT] = prev_staff_bar->extent (refp, Y_AXIS)[UP];
+      l[RIGHT] = staff_bar->extent (refp, Y_AXIS)[DOWN];
+
+      SCM smobbed_staff_bar = gh_car (elts);
+      Grob *staff_bar = unsmob_grob (smobbed_staff_bar);
+      SCM smobbed_interstaff_bar_molecule = 
+       Bar::compound_barline (staff_bar, glyph_str, l.length()).
+       smobbed_copy ();
+
+      Molecule *interstaff_bar_mol =
+       unsmob_molecule (smobbed_interstaff_bar_molecule);
+
+      yoffs += prev_staff_bar_length; // skip staff bar
+      yoffs += 0.5 * (l[RIGHT] - l[LEFT]); // compensate interstaff bar 
centering
+      interstaff_bar_mol->translate_axis (yoffs, Y_AXIS);
+      yoffs += 0.5 * (l[RIGHT] - l[LEFT]);
+
+      span_bar_mol.add_molecule (*interstaff_bar_mol);
+    }
+    prev_staff_bar = staff_bar;
+    prev_staff_bar_length = staff_bar_length;
+  }
+
+  return span_bar_mol.smobbed_copy ();
+}
+
 MAKE_SCHEME_CALLBACK (Span_bar,width_callback,2);
 SCM
 Span_bar::width_callback (SCM element_smob, SCM scm_axis)

###############################################################################

span-bar-test.ly:

\score {
 \notes \relative c' \context StaffGroup = groupie <
  \context Staff = SA { c1 c1 c1}
  \context Lyrics = LA \lyrics <
   { bla1 die bla }
  >
  \context Staff = SB { a1 a1 a1}
  \context Lyrics = LB \lyrics <
   { bla1 die bla }
   { foo bar foo }
  >
  \context Staff = SC { f1 f1 f1}
  \context Lyrics = LC \lyrics <
   { bla1 die bla }
   { foo bar foo }
   { foo bar foo }
  >
  \context Staff = SD { d1 d1 d1}
  \context Lyrics = LD \lyrics <
   { bla1 die bla }
   { foo bar foo }
   { foo bar foo }
   { foo bar foo }
  >
 >
 \paper {
  \translator {
   \StaffContext
   BarLine \override #'transparent = ##t
  }
 }
}

###############################################################################



reply via email to

[Prev in Thread] Current Thread [Next in Thread]