lilypond-user
[Top][All Lists]
Advanced

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

Re: big (?) challenge: multi-segment / multi-angle OttavaBracket


From: Thomas Morley
Subject: Re: big (?) challenge: multi-segment / multi-angle OttavaBracket
Date: Sun, 20 Dec 2015 22:21:13 +0100



2015-12-19 23:43 GMT+01:00 Kieren MacMillan <address@hidden>:
Hello all,

The final line of the song I’m currently engraving looks like this:

Questions:

1. How could I [best?] code this so that the OttavaBracket starts close to the top of the staff at the beginning of m. 31 (the Ab), angles upward at the third quarter of m. 33 (the Db), and then flattens out again for the last two triplet-eighths (the high Bb)?

2. Can this kind of “multi-segment” OttavaBracket (or, more generally, spanner) be automated and/or sugar-i-fied?

Thanks for any hints/links/help,
Kieren.

Hi Kieren,

you don't provide any code ;)
And I really dislike inline-images.

That said, it's not that easy ...
Below some code, which hopefully does what you want, though it's a quite terrible user-interface, if one can call it so at all.
Every layout-change will likely result in the need of readjusting...
At least it works.

It would be far simpler if one could add an option to make-path-stencil to draw dashed lines. Like pure postscript in the following markup-example:

\markup
  \postscript
    #"
     [0.5 0.5] 0.1 setdash
     0 0 moveto
     3 0 lineto
     5 3 lineto
     7 3 lineto
     7 2 lineto
     stroke
    "

But I found no way to do so. Thus I defined `make-dashed-line-stencil' and `make-connected-dashed-line-stencil' first.
With `kneed-line' I try to give you a little easier to use code at hand, but I'm really not convinced.

Anyway here the code:

\version "2.19.32"

#(define (make-dashed-line-stencil width startx starty endx endy)
"Make a dashed line stencil of given linewidth and set its extents accordingly."
  (let ((xext (ordered-cons 0 (- endx startx)))
        (yext (ordered-cons 0 (- endy starty)))
        (x (- endx startx))
        (y (- endy starty)))
    (ly:make-stencil
      ;; the numerical values in the line below determine the appearance
      ;; of the dashes, the last one is the `phase', i.e. where to start
      ;; the dashed-line
      (list 'dashed-line  width 0.4 0.6 x y 0)
      ;; Since the line has rounded edges, we have to / can safely add half the
      ;; width to all coordinates!
      (interval-widen xext (/ width 2))
      (interval-widen yext (/ width 2))
      ;xext
      ;yext
      )))
    
#(define (make-connected-dashed-line-stencil points-list thickness)
"Connect the given points with dashed-lines"
  
  (define (coords->listed-coords coords-list)
    (map
      (lambda (x y) (append x y))
      (cons (list 0 0) coords-list)
      coords-list))
 
  (let* ((coords (coords->listed-coords points-list)))
    (apply
      ly:stencil-add
      (map
        (lambda (coord x-move)
          (ly:stencil-translate
            (make-dashed-line-stencil
              thickness
              (car coord)
              (cadr coord)
              (caddr coord)
              (cadddr coord))
          (cons (car coord) (cadr coord))))
        coords
        (cons 0 (map car coords))))))
       
#(define ((kneed-line coords start-offset) grob)
"Create a (dashed) line for overriding @code{OttavaBracket.stencil} based on a
list of @var{coords} in @code{(cons x y)} form.  @code{x} is the portion of the
width consumed for a given line and @code{y} is the portion of the height. 
For example, @code{'((0.3 . 0.7) (0.8 . 0.9) (1.0 . 1.0))} means that at the
point where the hairpin has consumed 30% of its width, it must be at 70% of its
height.  Once it is to 80% width, it must be at 90% height.  It finishes at
100% width and 100% height.
"
  (define (pair-to-list pair)
    (list (car pair) (cdr pair)))
   
  (define (normalize-coords goods x y)
    (map
     (lambda (coord)
       (cons (* x (car coord)) (* y (cdr coord))))
     goods))
    
  (define (my-c-p-s points thick)
    ;(make-connected-path-stencil
    ; points
    ; thick
    ; 1.0
    ; 1.0
    ; #f
    ; #f)
    (make-connected-dashed-line-stencil points thick)
    )
  ;; outer let to trigger suicide
  (let ;((sten (ly:line-spanner::print grob)))
       ((sten (ly:ottava-bracket::print grob)))
    (if (grob::is-live? grob)
        (let* ((thick (ly:grob-property grob 'thickness 1))
               (thick (* thick (layout-line-thickness grob)))
               (xex (ly:stencil-extent sten X))
               (lenx (- (interval-length xex) (car start-offset)))
               (yex (ly:stencil-extent sten Y))
               (leny (interval-length yex))
               (xtrans (car xex))
               (ytrans (car yex))
               (uplist (map pair-to-list
                            (normalize-coords coords lenx (/ leny 2)))))
          (ly:stencil-add
            (ly:stencil-translate
              (my-c-p-s uplist thick)
             (cons (+ xtrans (car start-offset)) (+ ytrans (cdr start-offset))))
            (grob-interpret-markup grob (ly:grob-property grob 'text))))
        '())))
       
#(define (kneed-spanner buckles height start-offset)
  (kneed-line
    `((0 . 0)
      (,(car buckles) . 0)
      (,(cadr buckles) . ,height)
      (1 . ,height)
      (1 . ,(- height 1)))
    start-offset))
 
kneedSpanner =
#(define-music-function (parser location buckles height start-offset)
  (number-list? number? number-pair?)
"Returns a kneed dashed line, overriding @code{OttavaBracket.stencil}.
Relying on the settings of @code{kneed-spanner}
"
#{
  \override Staff.OttavaBracket.stencil =
    #(kneed-spanner buckles height start-offset)
  \override Staff.OttavaBracket.outside-staff-priority = ##f
#})

>  \kneedSpanner #'(0.85 0.9) #3.5 #'(4.5 . 1.6)
  \key aes \major
 
  \ottava #1
  \tuplet 6/4 {
    \change Staff = "down" aes'8[
    \change Staff = "up" des'''
    \change Staff = "down" f''
    \change Staff = "up" bes''
    \change Staff = "down" ees''
    \change Staff = "up" aes''']~
  }
  aes'''4
  \tuplet 3/2 {
    \change Staff = "down" bes'8
    f''
    \change Staff = "up" des'''
  }
  \tuplet 6/4 {
    \change Staff = "down" b'8[
    \change Staff = "up" e'''
    \change Staff = "down" a''
    \change Staff = "up" dis'''
    \change Staff = "down" fis''
    \change Staff = "up" gis''']
  }
  cis''' a''' fis''' b'''
  \tuplet 6/4 {
    \change Staff = "down" des''8[
    \change Staff = "up" f'''!
    \change Staff = "down" aes''!
    \change Staff = "up" ees'''!
    \change Staff = "down" bes''
    \change Staff = "up" bes'''!]
  }
  \tuplet 6/4 {
    des'''![
    aes'''!
    des''''
    ees''''
    bes''''
    aes'''']~
  }
  aes''''1
  \bar "|."
}
<<
  \new Staff { \clef bass \key aes \major aes1~ aes4 r4 r2 R1*2 }
  \addlyrics { ress. __ }
  \new PianoStaff <<
    \new Staff = "up" { \tempo "Tempo Primo" 4=108 \one }
    \new Staff = "down" { \key aes \major s1 s2 r s r R1 }
  >>
>>


Nevertheless, hth,
  Harm

Attachment: atest-28.png
Description: PNG image


reply via email to

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