Menu

#5539 TextSpanner: left text incorrectly influences dashes

Accepted
nobody
None
Defect
2019-08-07
2019-07-20
No

[git commit 49f41bf1c64ae1e2490571e73a85cbc4b2a9fb27]

\version "2.21.0"

\header { texidoc = "
  For a text spanner, the length of the (left) text element
  must not influence the distance between and the length of
  dashes.

  Here is a counterexample.
" }

\relative c' {
  \override TextSpanner.dash-period = #8
  \override TextSpanner.dash-fraction= #0.1

  \override TextSpanner.bound-details.left.text = "im"
  e1\startTextSpan e1 e1\stopTextSpan

  \override TextSpanner.bound-details.left.text = "immer"
  e1\startTextSpan e1 e1\stopTextSpan
}
1 Attachments

Discussion

  • Werner LEMBERG

    Werner LEMBERG - 2019-07-20
    • Type: --> Defect
     
  • Thomas Morley

    Thomas Morley - 2019-07-20

    Hi Werner,

    I disagree.
    The dashed line of a TextSpanner must start right after left-text. It must end right before right-text or as in your example at the target NoteColumn. (for line-breaks similar).

    This can't be warranted while exactly following the user-setted dash-period/fraction.
    Some scaling is always needed. Otherwise the dashed line will be too short or too long.

    In your eample:
    If I read out the dashed-line-settings from the 'stencil I get:

    %% im      
          (dashed-line
            0.1
            0.672281764072063
            6.05053587664857
            14.1179170455133
            0.0
            0.0))
    
    %% immer
          (dashed-line
            0.1
            0.926494248232063
            8.33844823408857
            10.1914367305527
            0.0
            0.0)
    

    dashed-line has settings for thickness, on, off, x-destination, y-destination and phase (in this order)

    IIUC:
    on, off are the here relevant variables, influenced by dash-period/fraction,
    note: dash-fraction is a percentage not an absolute value.
    'on' is the printed part
    'off' is the white space part

    So in the first example (+ on off on off on) should lead to the x-destination, which is correct.
    In the second example (+ on off on) should lead to the x-destination, which is correct as well.

    OTOH (+ on off) is in both cases not the setted dash-period:
    6.722817640720633 for the first, 9.264942482320633 for the second stencil.

    Looks like lily scales both, the length of the printed dash and the white space between them to find an accaptable trade-off.

    Whether current approach is the best, may be discussable, but you can't avoid scaling, imho.
    In the draw-dashed-line-markup which I implementd some time ago, I scaled 'on' only for a rare corner case (very short line) otherwise only 'off' is tackled.

     
  • Werner LEMBERG

    Werner LEMBERG - 2019-07-20

    No, no, no, I explicitly set period and fraction, and LilyPond silently overrides my values, replacing them with a very ugly trade-off in the given example, and I have zero chance to get what I want without ad-hoc fiddling of the parameters. This can't be right!

    IMHO we must have a new option that makes lilypond behave exactly as specified by those parameters, without any scaling – at the cost of a larger gap after the left spanner text (we probably need another new parameter 'offset' to specify the maximum size of this gap). It is OK with me if the current behaviour you describe above is the default and the behaviour I want has to be activated separately.

     
    • Thomas Morley

      Thomas Morley - 2019-07-20

      For the already mentioned draw-dashed-line-markup one can specify full-length #f to insist on the given on/off-values.

      In the code below I added such a markup with full-length #f, on 0.8, off 8. (It's red colored.)
      Which mimics the settings for dash-fraction/period in your initial example.
      The markup is moved in order to start exactly where the default dashed-text-spanner-line starts. Values for that are calculated based on the spanner-stencil values. See the commented code for ly:stencil-expr.

      \relative c' {
        \override TextSpanner.dash-period = #8
        \override TextSpanner.dash-fraction= #0.1
      
        \override TextScript.color = #red
      
      %  \override TextSpanner.after-line-breaking =
      %  #(lambda (grob)
      %    (pretty-print
      %      (ly:stencil-expr (ly:grob-property grob 'stencil))))
      
        <>^\markup 
              \translate #'(2.913177952755998 . 0)
              \override #'(full-length . #f)
              \override #'(on . 0.8)
              \override #'(off . 8)
              \draw-dashed-line #'(14.1179170455133 . 0)
      
        \override TextSpanner.bound-details.left.text = "im"
        e1\startTextSpan e1 e1\stopTextSpan
      
        <>^\markup 
              \translate #'(6.839658267716501 . 0)
              \override #'(full-length . #f)
              \override #'(on . 0.8)
              \override #'(off . 8)
              \draw-dashed-line #'(10.1914367305527 . 0)
      
        \override TextSpanner.bound-details.left.text = "immer"
        e1\startTextSpan e1 e1\stopTextSpan
      }
      

      Attached the output image.

      I think something like the red markup should never become the default.
      Even as an option - - - why?

      Ok, I had coded that full-length-true/false-option in the markup myself.
      But this was pure paranoia ...

      Though, I'm afraid implementing such an option into TextSpanner.stencil would mean C++-work. So I can't do it myself.

       
  • Werner LEMBERG

    Werner LEMBERG - 2019-07-21

    OK, thanks for that! What I can live with is that lilypond automatically (slightly) adjusts the space width between dashes. However, it's a definite no-go for me that lilypond adjusts the length of the dashes, too. This is against all typesetting rules – please remember that in former times the dash was not freely drawn but a glyph with a fixed horizontal extent.

    To be more precise, my original problem is not a single TextSpanner but a chain of it. My current (simplified) code is something like

    \override TextSpanner.bound-details.left.text = "foo"
    e1\startTextSpan
    \override TextSpanner.bound-details.left.text = "bar"
    e1\stopTextSpan\startTextSpan
    \override TextSpanner.bound-details.left.text = "baz"
    \override TextSpanner.bound-details.left.right = "umpf"
    e1\stopTextSpan
    

    Maybe it makes sense to extend the TextSpanner grob to support this explicitly. Lilypond would then automatically compute the widths of all gaps between the text strings to get a uniform look.

     
    • Thomas Morley

      Thomas Morley - 2019-07-21

      There must be typos in your example code, thus I don't understand what you want to demonstrate. Could you elaborate?

      Nevertheless, if you comment the lines with
      \override #'(full-length . #f)
      in my markup-code above, then the dashed-line starts/ends exactly. It ensures the line starts and ends with a dash. The dash itself is not scaled.
      Though the off-values (specified was 8.0) is scaled to 12.5179170455133 and 8.5914367305527
      So, in one case the provided value is scaled by ~150%
      I wouldn't call this slightly...
      But I don't see a way to avoid such a big scaling for certain off-values (the dash-period), if we want to ensure dashes at start and end of the line.

      IIUC, the situation for TextSpanners is as follows:
      'dash-period can be specified, then lily calculates how to scale the setted dash-period to ensure full line-extent.
      And then the dash-fraction is applied to the scaled value.
      As a consequence this results in different dash-extends (on-values).

      In the markup command I tried to keep the dash-extend wherevere possible.
      Only for small lines I implemented some conditions to either drop the line or print a dot or print a solid line.
      For TextSpanners one could probably implement some settable not scaleable on-value (for the dash-extend), a scaleable off-value (for the white-space) and go for treshold-conditions like:
      if no room for 1 dash, drop the line
      if no room for 2 dashes, print a solid line
      else scale the off-value to fit.

       
  • Thomas Morley

    Thomas Morley - 2019-07-21

    Attached the beginning of a workaround.
    Note: only left edge of TextSpanner is cared for, the default-stencil is added as well, red colored and slightly moved (for reference)
    Play around with dash-period/fraction to watch (dis-)advantages.

     
    • Thomas Morley

      Thomas Morley - 2019-07-21

      And the image for it

       
  • Werner LEMBERG

    Werner LEMBERG - 2019-07-22

    You are right, there were typos in my example. Sorry for that. Here is something updated, together with an image.

    \paper {
      indent = 0\cm
      ragged-right = ##f
      line-width = 16\cm
    }
    
    \relative c' {
      \override TextSpanner.dash-fraction = #0.1
      \override TextSpanner.dash-period = #8
      \override TextSpanner.bound-details.left.padding = #1
    
      \override TextSpanner.bound-details.left.text = "foo"
      e1\startTextSpan |
      \override TextSpanner.bound-details.left.text = "bar"
      e8\stopTextSpan\startTextSpan e e e e e e e |
      \override TextSpanner.bound-details.left.text = "baz"
      \override TextSpanner.bound-details.right.text = "umpf"
      e4\stopTextSpan\startTextSpan e e e |
      e1\stopTextSpan
    }
    

    I would like to enter this as something like

    \relative c' {
      \override TextSpanner.dash-fraction = #0.1 % fixed
      \override TextSpanner.dash-period = #8     % a hint for LilyPond
    
      \override TextSpanner.text = #'("foo" "bar" "baz" "umpf")
      e1\startTextSpan |
      e8 e e e e e e e |
      e4 e e e |
      e1\stopTextSpan
    }
    

    and let LilyPond find out a good value for dash-period (based on the suggested value) that looks nice for all sub-spanners.

     
  • Werner LEMBERG

    Werner LEMBERG - 2019-07-22

    Oops, in my 'would like to enter' example, the dash-fraction line should rather be something like

    \override TextSpanner.dash-length = #1 % fixed
    

    to get an absolute value, not a fraction of something.

     
  • Simon Albrecht

    Simon Albrecht - 2019-08-07
    • status: New --> Accepted