lilypond-user
[Top][All Lists]
Advanced

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

Re: DurationLine avoiding RehearsalMarks


From: Jean Abou Samra
Subject: Re: DurationLine avoiding RehearsalMarks
Date: Mon, 11 Apr 2022 18:04:52 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.7.0

Le 11/04/2022 à 17:20, Thomas Morley a écrit :
Well, your example prints as I would wish it should.
Alas, there are obviously different opinions. Look at:
\layout {
    \context {
      \Voice
      \consists Duration_line_engraver
    }
}

<<
    \new Staff {
          \override Glissando.breakable = ##t
          c'1(\-\startTextSpan\glissando \break s1 c''1)\stopTextSpan
    }
    \new Staff { s1 \key cis \major s1 s1 }
>>
Not all spanners start/end equal.
Imho, it's a mess which needs design decisions.



Hm. That's right. Let's consider another example:

\version "2.23.8"

\layout {
  \context {
    \Voice
    \consists Duration_line_engraver
  }
}

\paper {
  ragged-right = ##t
}

<<
  \new Staff { c'1\- \break c'1 }
  \new Staff { c'1 \breathe c'1 }
>>


Well, maybe it doesn't make sense anyway -- I don't think I've
ever seen a breathing sign in one staff and not another.

Though, if this is something we want to support, I think we'll
agree that the duration line in the upper staff should not be
affected by the breathing sign, as the breathing sign doesn't
apply to that staff.

Making the DurationLine affected only by breakable items in
its staff is easy to define (implementation: see below). If
we decide that we want different behaviors for different breakable
items, like KeySignature vs. BreathingSign, a definition is
going to be trickier ...


How about adding a Scheme interface for Axis_group_interface::staff_extent
from lily/axis-group-interface.cc and using it in duration-line::print?
Please remember I don't know C++, thus I don't fully understand what's
done in lily/axis-group-interface.cc, same for the porting to scheme.
Maybe some comments would help.


Do you mean code comments? Or comments from me in this email?
There is a (lonely) comment above staff_extent in the source:

/* This is like generic_group_extent, but it only counts the grobs that
   are children of some other axis-group. This is uncached; if it becomes
   commonly used, it may be necessary to cache it somehow. */


In short: it's roughly like ly:relative-group-extent, except that
it only takes the combined extents of grobs that are children of
a certain grob on a certain axis.


Obviously grob::has-in-ancestry? is a predicate. It becomes #t if
`potential-ancestor' (the StaffSymbol we're in?) is found.
(Btw, in the recursion "?" is missing)

It essentially does the same as (untested code):

#(define (grob::has-in-ancestry? grob potential-ancestor axis)
     (or (eq? grob potential-ancestor)
         (let ((parent (ly:grob-parent grob axis)))
           (and (not (null? parent))
                (grob::has-in-ancestry parent potential-ancestor axis)))))
Though, what's below? I've difficulties with the arguments.
`axis-group' is likely the VerticalAxesGroup: (ly:grob-object grob
'axis-group-parent-Y) ?
`refpoint' is (ly:grob-system grob) ?
`staff' is  (ly:grob-object grob 'staff-symbol) ?
What are `ext-axis' and `parent-axis' meant for?



The typical case would be

(axis-group-interface::staff-extent [NonMusicalPaperColumn] [System] X [VerticalAxisGroup] Y)

which gives you the width of the NonMusicalPaperColumn "on the
staff VerticalAxisGroup": instead of taking the union of the widths
of all breakable items in the NonMusicalPaperColumn, you just take
the extents of those items that are children of the VerticalAxisGroup.
If there are items on other staves, they are ignored in this
calculation.

My Scheme mock-code was meant to explain what this function
did (well, it would have been clearer if I had explained it with
words ...), but of course it would be preferable to export it from
C++, to avoid code duplication. If you want to experiment with it
in a patch, you can do the exporting part with

diff --git a/lily/axis-group-interface.cc b/lily/axis-group-interface.cc
index ede8e9686c..a7ad87791c 100644
--- a/lily/axis-group-interface.cc
+++ b/lily/axis-group-interface.cc
@@ -256,6 +256,25 @@ Axis_group_interface::staff_extent (Grob *me, Grob *refp, Axis ext_a, Grob *staf
   return relative_group_extent (new_elts, refp, ext_a);
 }

+MAKE_DOCUMENTED_SCHEME_CALLBACK (Axis_group_interface, selective_extent, 5,
+                                 R"(
+Return the combined extent of elements from @var{grob} on @var{axis}
+relative to @var{refpoint}.  Only retain those elements that are children
+of @var{staff} on @var{parent-axis}.
+                                 )");
+SCM
+Axis_group_interface::selective_extent (SCM grob, SCM refpoint, SCM axis, SCM staff, SCM parent_axis)
+{
+  auto *const g = LY_ASSERT_SMOB (Grob, grob, 1);
+  auto *const r = LY_ASSERT_SMOB (Grob, refpoint, 2);
+  LY_ASSERT_TYPE (is_scm<Axis>, axis, 3);
+  Axis a = from_scm<Axis> (axis);
+  auto *const s = LY_ASSERT_SMOB (Grob, staff, 4);
+  LY_ASSERT_TYPE (is_scm<Axis>, parent_axis, 5);
+  Axis pa = from_scm<Axis> (parent_axis);
+  return to_scm (staff_extent (g, r, a, s, pa));
+}
+
 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_relevant_grobs, 1);
 SCM
 Axis_group_interface::calc_pure_relevant_grobs (SCM smob)
diff --git a/lily/include/axis-group-interface.hh b/lily/include/axis-group-interface.hh
index 46f3369c05..4300e9a60a 100644
--- a/lily/include/axis-group-interface.hh
+++ b/lily/include/axis-group-interface.hh
@@ -47,6 +47,7 @@ public:
   DECLARE_SCHEME_CALLBACK (calc_pure_staff_staff_spacing, (SCM, SCM, SCM));
   DECLARE_SCHEME_CALLBACK (calc_pure_relevant_grobs, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_pure_y_common, (SCM));
+  DECLARE_SCHEME_CALLBACK (selective_extent, (SCM, SCM, SCM, SCM, SCM));
   static SCM internal_calc_pure_relevant_grobs (Grob *, const std::string &);
   static Interval relative_group_extent (std::vector<Grob *> const &list,
                                          Grob *common, Axis);
@@ -72,4 +73,3 @@ public:
 };

 #endif /* AXIS_GROUP_INTERFACE_HH */
-
diff --git a/lily/include/lily-guile-macros.hh b/lily/include/lily-guile-macros.hh
index 59fdd9c497..1842d70bc8 100644
--- a/lily/include/lily-guile-macros.hh
+++ b/lily/include/lily-guile-macros.hh
@@ -120,6 +120,12 @@ struct ly_scm_func_of_arity<4>
   typedef SCM (*ptr_type) (SCM, SCM, SCM, SCM);
 };

+template <>
+struct ly_scm_func_of_arity<5>
+{
+  typedef SCM (*ptr_type) (SCM, SCM, SCM, SCM, SCM);
+};
+
 /*
   Make TYPE::FUNC available as a Scheme function.
 */



(with whatever name: staff-extent, selective-extent, etc.)
Example usage:

diff --git a/scm/output-lib.scm b/scm/output-lib.scm
index 553c2536c0..7f1e5fcf82 100644
--- a/scm/output-lib.scm
+++ b/scm/output-lib.scm
@@ -2652,7 +2652,12 @@ The final stencil is adjusted vertically using @var{staff-space}, which is            ;; For a broken DurationLine take line-starting grobs into account.
           ;; Otherwise use left-bound directly
           (cond ((not-first-broken-spanner? grob)
-                 (ly:grob-robust-relative-extent left-bound left-bound X))
+                 (ly:axis-group-interface::selective-extent
+                  left-bound
+                  left-bound
+                  X
+                  (ly:grob-object grob 'axis-group-parent-Y)
+                  Y))
                 (else left-note-column-main-X-ext)))
          ;; `left-X' is line-starting X-coordinate relative to grob's system           ;; NB the final line-stencil will start at left-bound not at `left-X'



Cheers,
Jean




reply via email to

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