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