2017-04-21 14:39 GMT+02:00 David Nalesnik <david.nales...@gmail.com>:
> Hi,
>
> On Fri, Apr 21, 2017 at 1:07 AM,  <u...@openlilylib.org> wrote:
>> Am 2017-04-21 07:41, schrieb Nathan Ho:
>>>
>>> On 2017-04-20 20:42, Andrew Bernard wrote:
>>>>
>>>> I posted a while ago with a query about hairpins, to which no
>>>> response.
>>>>
>>>> Would there be any way to have hairpins that don't start, or end in
>>>> the other direction, with the lines converging to the same point? I
>>>> have need from time to time of hairpins where the end points are still
>>>> separated, rather than coming to a termination together. Sure this can
>>>> be done with a whiteout box, but that is always fiddly and the
>>>> position tends to move when the score is repaginated etc etc. In the
>>>> same way as the 'height' property allows you to specify the separation
>>>> at the open end, it would be useful to have some property for this
>>>> sort of thing at the pointy end. Yes, definitely not Common Era
>>>> engraving practice, but this keeps coming up in the New Complexity
>>>> scores I work with.
>
> Besides Nathan's code below, you might be able to use the
> "Ferneyhough" hairpins.
>
> Can you provide an usage example of these partial hairpins?  How would
> they behave over line breaks?

The code for "Ferneyhough" hairpins uses make-connected-path-stencil,
hence it will not work for this purpose.

Below a rewrite using make-path-stencil:

#(define ((elbowed-hairpin coords mirrored?) grob)
  "Create hairpin 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 . 0) (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.
If @var{coords} does not begin with @code{'(0 . 0)} the final hairpin will have
an open tip.  For example '(0 . 0.5) will cause an open end of 50% of the usual
height.
@var{mirrored?} indicates if the hairpin is mirrored over the Y-axis or if
just the upper part is drawn.
Returns a function that accepts a hairpin grob as an argument
and draws the stencil based on its coordinates.

@lilypond[verbatim,quote]
#(define simple-hairpin
  (elbowed-hairpin '((0 . 0)(1.0 . 1.0)) #t))

\\relative c' {
  \\override Hairpin #'stencil = #simple-hairpin
  a\\p\\< a a a\\f
}
@end lilypond
"
  (define (normalize-coords goods x y)
    (map
      (lambda (coord)
        (cons (* x (car coord)) (* y (cdr coord))))
      goods))

  (define (my-c-p-s points thick decresc?)
    (let ((start-point (car points)))
      (make-path-stencil
        (append
          `(moveto
            ,(car start-point)
            ,(cdr start-point))
          (append-map
            (lambda (elt)
              (list 'lineto (car elt) (cdr elt)))
            (cdr points)))
        thick
        (if decresc? -1.0 1.0)
        1.0
        #f)))
  ;; outer let to trigger suicide
  (let ((sten (ly:hairpin::print grob)))
    (if (grob::is-live? grob)
        (let* ((decresc? (eqv? (ly:grob-property grob 'grow-direction) LEFT))
               (thick (ly:grob-property grob 'thickness 0.1))
               (thick (* thick (layout-line-thickness grob)))
               (xex (ly:stencil-extent sten X))
               (lenx (interval-length xex))
               (yex (ly:stencil-extent sten Y))
               (leny (interval-length yex))
               (xtrans (+ (car xex) (if decresc? lenx 0)))
               (ytrans (car yex))
               (uplist (normalize-coords coords lenx (/ leny 2)))
               (downlist (normalize-coords coords lenx (/ leny -2)))
               (stil
                 (ly:stencil-aligned-to
                   (ly:stencil-translate
                     (ly:stencil-add
                       (my-c-p-s uplist thick decresc?)
                       (if mirrored?
                           (my-c-p-s downlist thick decresc?)
                           empty-stencil))
                     (cons xtrans ytrans))
                   Y CENTER))
               (stil-y-extent (ly:stencil-extent stil Y)))
        ;; Return a final stencil properly aligned in Y-axis direction and with
        ;; proper extents. Extent in X-axis direction is taken from the
        ;; original, in Y-axis direction from the new stencil.
        ;; Otherwise stencil-operations like 'box-stencil' will return badly.
        (ly:make-stencil (ly:stencil-expr stil) xex stil-y-extent))
        ;; return empty if no Hairpin.stencil present.
        '())))

%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLE
%%%%%%%%%%%%%%%%%%%%%%

{
  \override Hairpin.to-barline = ##f
  \once \override Hairpin.stencil =
    #(elbowed-hairpin '((0.0 . 0.4)(1.0 . 1.2)) #t)
  c'4\> c'' c''' d'''\! d'''1

  \once \override Hairpin.stencil =
    #(elbowed-hairpin '((0.0 . 0.0)(1.0 . 0.5)) #t)
  c'1\pp\<
  \once \override Hairpin.stencil =
    #(elbowed-hairpin '((0.0 . 0.5)(1.0 . 1.0)) #t)
  d'\mf\< e'\ff\!
  \break
  \once \override Hairpin.stencil =
    #(elbowed-hairpin
      '((0.0 . 0.2) (0.2 . 1.2)(0.4 . 0.2) (0.6 . 3)(0.8 . 1.5)(1.0 . 1.0)) #t)
  c'1*3\> c'1\!

}

Probably worth a patch.
Though, it will return not very nice at line-breaks (as before).
One could do so by adding a lot of code covering this case.
But ugh ...
Better if we could introduce a property whether the lines of the
hairpin should connect or not (and with which gap).
We already have Hairpin.height for the open end of a Hairpin...

Cheers,
  Harm

>
>>>
>>> hi andrew,
>>>
>>> check it out:
>>>
>>> #(define ((open-hairpin left-open right-open) grob)
>>>    (let* ((stencil (ly:hairpin::print grob))
>>>           (X-ext (ly:stencil-extent stencil X))
>>>           (Y-ext (ly:stencil-extent stencil Y))
>>>           (width (interval-length X-ext))
>>>           (height (interval-length Y-ext)))
>>>      (ly:stencil-translate
>>>        (grob-interpret-markup grob
>>>          (markup
>>>            (#:path 0.1
>>>              (list (list 'moveto 0 (* height (- 0.5 (* 0.5 left-open))))
>>>                    (list 'lineto width (* height (- 0.5 (* 0.5
>>> right-open))))
>>>                    (list 'moveto 0 (* height (+ 0.5 (* 0.5 left-open))))
>>>                    (list 'lineto width (* height (+ 0.5 (* 0.5
>>> right-open))))))))
>>>        (cons 0 (interval-start Y-ext)))))
>>>
>>> {
>>>   c'1\> c'1 c'1\!
>>>   \once \override Hairpin.stencil = #(open-hairpin 1.0 0.5)
>>>   c'1\> c'1 c'1\!
>>>   \once \override Hairpin.stencil = #(open-hairpin 0.5 0.0)
>>>   c'1\> c'1 c'1\!
>>> }
>>>
>>> respects height, but not thickness. anyone know how to convert a
>>> thickness value into staff spaces?
>>
>>
>> If I'm not mistaken this actually is a missing piece of information in
>> LilyPond.
>> The thickness is interpreted as relative to the staffline thickness, and
>> there's no general property for it.
>> It should be possible to use something like (untested)
>>
>> (hairpin-thickness (* (ly:staff-symbol-line-thickness grob)
>> (ly:grob-property grob 'thickness)))
>>
>> in the let-block and use hairpin-thickness in the markup generation.
>>
>
> Yes, this would work
>
> Instead of using a markup, why not use ly:line-interface::line
> (available from 2.19.27)? This gets thickness from the grob--and any
> other line attributes you want, so you can create dashed hairpins,
> whatever.  There's no need adjust thickness in this case.
>
> HTH,
> David
>
> _______________________________________________
> lilypond-user mailing list
> lilypond-user@gnu.org
> https://lists.gnu.org/mailman/listinfo/lilypond-user

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

Reply via email to