Am 17.08.2015 um 00:53 schrieb Thomas Morley:
2015-08-17 0:18 GMT+02:00 Simon Albrecht <simon.albre...@mail.de>:
Lily is being very honest and makes a kind warning telling us that she
doesn’t know how to parenthesize spanners. But it would be really nice if we
could teach her that :-)

%%%%%%%%%%%%%%%%%%%%%%%%%%
\relative { c''-\parenthesize \> c c c
   c2\! -\parenthesize ~ c
}
%%%%%%%%%%%%%%%%%%%%%%%%%%

<https://code.google.com/p/lilypond/issues/detail?id=4565>

I once made the attached code.
It still compiles. You will observe several warnings, they are intended ;)
I never had the time and energy to finish it.
May be a good starting point, though.
I made an updated version for 2.19.24 and newer (…), which you find attached. Main differences:
– syntax updates, through convert-ly and manual
– code reformatting (minor)
– Both music functions now take a symbol list instead of a string, which simplifies the code.

The only noticeable flaw I found is the interleaving tie parentheses and the collisions with \par Stem or \par Flag. Also, with the first clef, inside padding is too large and outside padding too small in my eyes.
But other than that it works very well. Thanks again!
Simon
\version "2.19.24"
% courtesy of Thomas Morley
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% The following untouched defs need to be here, because they aren’t public.

#(define (make-bezier-sandwich-stencil coords thick xext yext)
   (let* ((command-list `(moveto
                          ,(car (list-ref coords 3))
                          ,(cdr (list-ref coords 3))
                          curveto
                          ,(car (list-ref coords 0))
                          ,(cdr (list-ref coords 0))
                          ,(car (list-ref coords 1))
                          ,(cdr (list-ref coords 1))
                          ,(car (list-ref coords 2))
                          ,(cdr (list-ref coords 2))
                          curveto
                          ,(car (list-ref coords 4))
                          ,(cdr (list-ref coords 4))
                          ,(car (list-ref coords 5))
                          ,(cdr (list-ref coords 5))
                          ,(car (list-ref coords 6))
                          ,(cdr (list-ref coords 6))
                          closepath)))
     (ly:make-stencil
      `(path ,thick `(,@' ,command-list) 'round 'round #t)
      xext
      yext)))

#(define (make-parenthesis-stencil
          y-extent half-thickness width angularity)
   "Create a parenthesis stencil.
@var{y-extent} is the Y extent of the markup inside the parenthesis.
@var{half-thickness} is the half thickness of the parenthesis.
@var{width} is the width of a parenthesis.
The higher the value of number @var{angularity},
the more angular the shape of the parenthesis."
   (let* ((line-width 0.1)
          ;; Horizontal position of baseline that end points run through.
          (base-x
           (if (< width 0)
               (- width)
               0))
          ;; X value farthest from baseline on outside  of curve
          (outer-x (+ base-x width))
          ;; X extent of bezier sandwich centerline curves
          (x-extent (ordered-cons base-x outer-x))

          (bottom-y (interval-start y-extent))
          (top-y (interval-end y-extent))

          (lower-end-point (cons base-x bottom-y))
          (upper-end-point (cons base-x top-y))

          (outer-control-x (+ base-x (* 4/3 width)))
          (inner-control-x (+ outer-control-x
                             (if (< width 0)
                                 half-thickness
                                 (- half-thickness))))

          ;; Vertical distance between a control point
          ;; and the end point it connects to.
          (offset-index (- (* 0.6 angularity) 0.8))
          (lower-control-y (interval-index y-extent offset-index))
          (upper-control-y (interval-index y-extent (- offset-index)))

          (lower-outer-control-point
           (cons outer-control-x lower-control-y))
          (upper-outer-control-point
           (cons outer-control-x upper-control-y))
          (upper-inner-control-point
           (cons inner-control-x upper-control-y))
          (lower-inner-control-point
           (cons inner-control-x lower-control-y)))

     (make-bezier-sandwich-stencil
      (list
       ;; Step 4: curve through inner control points
       ;; to lower end point.
       upper-inner-control-point
       lower-inner-control-point
       lower-end-point
       ;; Step 3: move to upper end point.
       upper-end-point
       ;; Step 2: curve through outer control points
       ;; to upper end point.
       lower-outer-control-point
       upper-outer-control-point
       upper-end-point
       ;; Step 1: move to lower end point.
       lower-end-point)
      line-width
      (interval-widen x-extent (/ line-width 2))
      (interval-widen y-extent (/ line-width 2)))))

#(define (other-axis a)
   (remainder (+ a 1) 2))

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#(define-public (string-or-music? x)
   (or (string? x) (ly:music? x)))

#(define-public (parenthesize-stencil
                 stencil half-thickness width angularity padding size)
   "Add parentheses around @var{stencil}, returning a new stencil."
   (let* ((y-extent (interval-widen (ly:stencil-extent stencil Y) size))
          (lp (make-parenthesis-stencil
               y-extent half-thickness (- width) angularity))
          (rp (make-parenthesis-stencil
               y-extent half-thickness width angularity)))
     (ly:stencil-combine-at-edge
      (ly:stencil-combine-at-edge stencil X LEFT lp padding)
      X RIGHT rp padding)))

par =
#(define-music-function (arg)(symbol-list-or-music?)
   (if (symbol-list? arg)
       (let ((context-name 'Bottom)
             (grob-name #f))

         (if (> 2 (length arg))
             (set! grob-name (car arg))
             (begin
              (set! grob-name (list-ref arg 1))
              (set! context-name (list-ref arg 0))))
         
         (propertyOverride `(,context-name ,grob-name stencil)
           (lambda (grob)
             (let* ((function (assoc-get 'stencil (reverse (ly:grob-basic-properties grob))))
                    (staff-space (ly:staff-symbol-staff-space grob))
                    (staff-line-thickness (ly:staff-symbol-line-thickness grob)))

               (if (and (procedure-name function)
                        (ly:stencil? (function grob)))
                   (let* ((stil (function grob))
                          (stem-pos (ly:grob-property grob 'stem-attachment))
                          (y-extent (ly:stencil-extent stil Y))
                          (y-length (interval-length y-extent))
                          (factor (if (<= y-length (* staff-space 1.5)) 0.5 1)))
                     (if (equal? grob-name 'NoteHead)
                         (begin
                          (ly:input-warning (*location*) (_ "better use simple \\parenthesize for ~a") grob-name)
                          stil)
                         (parenthesize-stencil
                          stil
                          staff-line-thickness
                          (* 4 staff-line-thickness factor)
                          (* staff-line-thickness 4)
                          (* staff-line-thickness 3)
                          (* staff-line-thickness 2))))
                   (begin
                    (ly:input-warning (*location*) (_ "cannot find 'stencil of ~a to parenthesize") grob-name)
                    '())
                   )))
           ))
       (begin
        (if (memq 'event-chord (ly:music-property arg 'types))
            ;; arg is an EventChord -> set the parenthesize property
            ;; on all child notes and rests
            (for-each
             (lambda (ev)
               (if (or (memq 'note-event (ly:music-property ev 'types))
                       (memq 'rest-event (ly:music-property ev 'types)))
                   (set! (ly:music-property ev 'parenthesize) #t)))
             (ly:music-property arg 'elements))
            ;; No chord, simply set property for this expression:
            (set! (ly:music-property arg 'parenthesize) #t))
        arg)
       ))

revertStencil =
#(define-music-function (name)(symbol-list?)
   (let ((context-name 'Bottom)
         (grob-name #f))

     (if (> 2 (length name))
         (set! grob-name (car name))
         (begin
          (set! grob-name (list-ref name 1))
          (set! context-name (list-ref name 0))))
     (propertyRevert `(,context-name ,grob-name stencil))))


%%{
\relative c' {
  \par Score.BarNumber
  \par Score.RehearsalMark
  \once\par Staff.Clef
  \par Staff.TimeSignature
  \par Score.MetronomeMark

  \key g\major
  \tempo "Allegro"

  \compressFullBarRests
  \par TextSpanner
  \override TextSpanner.bound-details.left.text = "showing par "
  %\par Script
  c1-\par -> %-\par -!
  \startTextSpan
  \par MultiMeasureRest
  \par MultiMeasureRestNumber
  R
  R1*2
  R1*3
  R1*4
  R1*5
  R1*6
  R1*7
  \mark\default
  \revertStencil MultiMeasureRestNumber
  R1*8
  R1*9
  R1*10
  R1*11
  \once \par Staff.KeySignature
  \once \par Staff.KeyCancellation
  \key bes\major
  \par Hairpin
  c1\<
  \par BreathingSign
  \breathe
  \par "Stem"
  d1
  dis8[ e]
  \revertStencil Stem
  \par Flag
  dis8 \noBeam e s2
  \once\par Staff.BarLine
  \bar ":..:"
  e1\!
  \par TrillSpanner
  \par Tie
  c1\startTrillSpan ~
  c~
  c1*7/8 s1*1/8
  \stopTrillSpan
  d1
  \stopTextSpan
  \par TupletBracket
  \par TupletNumber
  \once\override TupletNumber.text =
  #(tuplet-number::non-default-fraction-with-notes 12 "8" 4 "4")
  \tuplet 3/2 { c4. d e f }
  %\par
  \par TextScript
  e1_\markup \override #'(line-width . 50) \wordwrap {
    Some text. Some text. Some text. Some text.
    Some text. Some text. Some text. Some text.
    Some text. Some text. Some text. Some text.
  }
  \once\par NoteColumn
  <c e g>
  \once\par Score.VerticalAxisGroup
  <c e g>4
  \par NoteHead
  c
  c'
}

_______________________________________________
bug-lilypond mailing list
bug-lilypond@gnu.org
https://lists.gnu.org/mailman/listinfo/bug-lilypond

Reply via email to