Am Do., 15. Aug. 2024 um 16:13 Uhr schrieb Thomas Morley <
thomasmorle...@gmail.com>:

>
> Hi,
>>
>> attached you'll find my attempt to create a style-sheet.
>> Please holler for all I misunderstood or forgot or for bugs.
>>
>> Cheers,
>>   Harm
>>
>
> I forgot:
> the version-statement is serious, you'll need to wait for that version.
> It will not work with 2.24. and 2.25.18. has a show-stopping bug:
> https://gitlab.com/lilypond/lilypond/-/merge_requests/2407
>
> Cheers,
>   Harm
>

2.25.19 is out now.
The internal 'display-cautionary is dropped with this version and needs to
be replaced by 'parenthesized.
See attached.

Cheers,
  Harm
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%                                                                        %%%%
%%%%                                                                        %%%%
%%%%                    Style-sheet GuitarPro                               %%%%
%%%%                                                                        %%%%
%%%%                                                                        %%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%%%
%%%% TabNoteHead
%%%%
#(define tab-note-head::taller-circled-stencil
  (grob-transformer 'stencil
   ;; Make stencil a little taller.
   ;; Print it circled for notes longer than a quarter, but not if
   ;; 'display-cautionary is true. In this case a different stem-length
   ;; should be used.
    (lambda (grob orig)
      (let ((dur-log (ly:grob-property grob 'duration-log))
            (cautionary?
              (ly:grob-property grob 'display-cautionary #f))
            (taller-stencil
              (ly:make-stencil
                (ly:stencil-expr orig)
                (ly:stencil-extent orig X)
                (interval-widen (ly:stencil-extent orig Y) 0.2))))
        (if (and (> 2 dur-log) (not cautionary?))
            (circle-stencil taller-stencil 0.1 0.1)
            taller-stencil)))))

%%%%
%%%% Stem
%%%%
#(define stem::tab-length
  (lambda (grob)
    ;; Read 'stem-begin-position, ensure unbeamed stems all end at the same
    ;; height.
    (let* ((dir (ly:grob-property grob 'direction 1))
           (staff-symbol (ly:grob-object grob 'staff-symbol))
           (staff-lines (ly:grob-property staff-symbol 'line-positions))
           (top-or-bottom-line
             (apply (if (positive? dir) max min) staff-lines))
           (stem-begin (ly:grob-property grob 'stem-begin-position))
           (details (ly:grob-property grob 'details))
           (out-side-staff-length
             (assoc-get 'out-side-staff-length details 10)))
      (+ (* dir top-or-bottom-line)
         out-side-staff-length
         (* dir -1 stem-begin)))))

#(define stem::tab-stem-begin-position
  ;; If 'display-cautionary is true let stems begin outside of tab-staff,
  ;; contolled by 'details.gap-to-staff.
  ;; For half notes the stem is shortened increasing the gap to
  ;; the staff-symbol, controlled by 'details-shorten-for-half-note.
  (lambda (grob)
    (let* ((nhds-array (ly:grob-object grob 'note-heads #f))
           (nhds (if nhds-array (ly:grob-array->list nhds-array) #f))
           (staff-pos
             (if nhds
                 (map
                   (lambda (tnhds)
                     (ly:grob-property tnhds 'staff-position))
                   nhds)
                 '()))
           (dir (ly:grob-property grob 'direction 1))
           (staff-symbol (ly:grob-object grob 'staff-symbol))
           (staff-lines (ly:grob-property staff-symbol 'line-positions))
           (staff-space (ly:staff-symbol-staff-space grob))
           (top-or-bottom-nhd-pos
             (apply (if (positive? dir) max min) staff-pos))
           (top-or-bottom-line
             (apply (if (positive? dir) max min) staff-lines))
           (dur-log (ly:grob-property grob 'duration-log))
           (details (ly:grob-property grob 'details))
           (gap-to-staff (assoc-get 'gap-to-staff details))
           (shorten-for-half-note
             (assoc-get 'shorten-for-half-note details)))
    (+ top-or-bottom-line
       (* staff-space dir
          (if (eqv? 1 dur-log)
              (+ gap-to-staff shorten-for-half-note)
              gap-to-staff))))))

#(define stem::change-given-tab-stem-begin-position
  (grob-transformer 'stem-begin-position
   ;; If 'display-cautionary is true let stems begin outside of tab-staff,
   ;; contolled by 'details.gap-to-staff.
   ;; For half notes the stem is shortened increasing the gap to
   ;; the staff-symbol, controlled by 'details-shorten-for-half-note.
   (lambda (grob orig)
     (let* ((nhds-array (ly:grob-object grob 'note-heads #f))
            (nhds (if nhds-array (ly:grob-array->list nhds-array) '())))
       (if (every-cautionary? nhds)
           (stem::tab-stem-begin-position grob)
           orig)))))

%%%%
%%%% Beam
%%%%
#(define tab-beam::positions
  (lambda (grob)
   ;; Looking at Stem.details.out-side-staff-length, ensure same length of
   ;; stems as for unbeamed stems.
   (let* ((stems-array (ly:grob-object grob 'stems #f))
          (stems (if stems-array (ly:grob-array->list stems-array) #f))
          (stem-details
            (if stems
                (ly:grob-property (car stems) 'details)
                '()))
          (beam-thick (ly:grob-property grob 'beam-thickness))
          (staff-space (ly:staff-symbol-staff-space grob))
          (out-side-staff-length
             (assoc-get 'out-side-staff-length stem-details))
          (dir (ly:grob-property grob 'direction))
          (pos
            ;; TODO why do we need to reduce `out-side-staff-length` by 1?
            (* dir (1- out-side-staff-length))))
     (cons pos pos))))

#(define tab-beam::stencil
  (lambda (grob)
   ;; While affecting beamed Stem's 'stem-begin-position and 'length we need
   ;; to recreate the stencil
   (let* ((stems-array (ly:grob-object grob 'stems #f))
          (stems (if stems-array (ly:grob-array->list stems-array) '())))

     (for-each
       (lambda (stem)
         (let* ((nhds-array (ly:grob-object stem 'note-heads #f))
                (nhds (if nhds-array (ly:grob-array->list nhds-array) #f)))
         (when (and nhds (every-cautionary? nhds))
           (ly:grob-set-property! stem 'stem-begin-position
             (stem::tab-stem-begin-position (car stems))))))
       stems)

     (for-each
       (lambda (stem)
         (let* ((nhds-array (ly:grob-object stem 'note-heads #f))
                (nhds (if nhds-array (ly:grob-array->list nhds-array) #f)))
         (when (and nhds (every-cautionary? nhds))
           (ly:grob-set-property! stem 'length
             (stem::tab-length stem)))))
       stems)

     (ly:beam::print grob))))

%%%%
%%%% DurationLine
%%%%
%%   bow-stencil for faking Tie
#(define duration-line::bow-stencil
  (lambda (grob)
    (let* ((vals (duration-line::calc grob))
           (left-start (assoc-get 'x-start vals))
           (right-end (assoc-get 'x-end vals))
           (thick (assoc-get 'thick vals))
           (dir (ly:grob-property grob 'direction -1)))
      (make-tie-stencil
        (cons left-start 0) ;; start
        (cons right-end 0)  ;; end
        thick ;thick
        dir ;orientation
        0.6 ; height-limit
        ))))

%%%%
%%%% BendSpanner
%%%%
#(define bend::target-visibility
;; Set details.target-visibility #t, but keep the target TabNoteHead
;;transparent, i.e. Stem, Flag and Dots become visible, but not the TabNoteHead
;; itself.
  (grob-transformer 'details
    (lambda (grob orig)
      (let ((right-bound (ly:spanner-bound grob RIGHT)))
        (if (ly:grob? right-bound)
            (begin
              (for-each
                (lambda (tnhd)
                  (ly:grob-set-property! tnhd 'transparent #t))
                (cdr (get-bound-note-heads grob)))
              (acons 'target-visibility #t orig))
            orig)))))

%% Short-cut
printTarget = -\tweak details #bend::target-visibility \etc

%%%%
%%%% Dots
%%%%
#(define tab-dots::staff-position
  (lambda (grob)
    (let* ((tnhd (ly:grob-parent grob Y))
           (stem (ly:grob-object tnhd 'stem))
           (details (ly:grob-property stem 'details))
           (out-side-staff-length
             (assoc-get 'out-side-staff-length details))
           (dir (ly:grob-property stem 'direction 1))
           (staff-pos (ly:grob-property tnhd 'staff-position))
           (staff-space (ly:staff-symbol-staff-space grob))
           (staff-symbol (ly:grob-object grob 'staff-symbol))
           (staff-lines (ly:grob-property staff-symbol 'line-positions))
           (top-or-bottom-line
             (apply (if (positive? dir) max min) staff-lines)))
    (if (negative? dir)
        (+
           (* dir staff-pos)
           top-or-bottom-line
           (* dir out-side-staff-length))
         ;; TODO
         ;; No clue how it should look for \stemUp
         0))))

%%%%
%%%% Helper
%%%%

#(define (every-cautionary? tab-note-heads)
  (every
     (lambda (x) (ly:grob-property x 'display-cautionary #f))
     tab-note-heads))

%%%%
%%%% layout
%%%%

guitarProStyleLayout =
  \layout {
    \context {
      \TabStaff
      \tabFullNotation
      \numericTimeSignature
      %% Stem
      \override Stem.layer = #-100
      \override Stem.details.out-side-staff-length = 7
      \override Stem.details.gap-to-staff = 1.5
      \override Stem.details.shorten-for-half-note = 1.0
      \override Stem.stencil = #ly:stem::print
      \revert Stem.X-extent
        \override Stem.stem-begin-position =
          #stem::change-given-tab-stem-begin-position
      \override Stem.length = #stem::tab-length
        %% TabNoteHead
      \override TabNoteHead.stem-attachment = #'(0 . 0)
      \override TabNoteHead.stencil = #tab-note-head::taller-circled-stencil
      %% Beam
      \override Beam.positions = #tab-beam::positions
      \override Beam.stencil = #tab-beam::stencil
      %% Dots
      \override Dots.staff-position = #tab-dots::staff-position
      \override DotColumn.padding = #-0.5
    }

    \context {
      \TabVoice
      \consists Duration_line_engraver
      \override DurationLine.stencil = #duration-line::bow-stencil
      \override DurationLine.bound-details.left.padding = 0.1
      \override DurationLine.bound-details.right.padding = 0.1
      \override DurationLine.thickness = 1.2
    }
  }
\version "2.25.19"

\include "guitar-pro-style.ly"

styleExample = {
  \clef "moderntab"
  g'2..\3 a'8\3~
  \once \override TabNoteHead.parenthesized = ##t
  a'2\3
  <<
    {
      \oneVoice
      a'8\2 f'8\3 \printTarget \^ s4*7/8\3 \tweak transparent ##t fis'1*1/32
    }
    \\
    {
      s8
      \once \hideNotes
      f'8\3 \-
      \once \override TabNoteHead.parenthesized = ##t
      \once \override TabNoteHead.transparent = ##t
      f'4
    }
  >>
  d'1\3

  \break

  g'2..\3 a'8\3~
  \once \override TabNoteHead.parenthesized = ##t
  a'2\3
  <<
    {
      \oneVoice
      a'8\2 f'\3 \printTarget \^ fis'4*7/8\3\bendHold \^
      \tweak transparent ##t fis'1*1/32
    }
    \\
    {
      s8
      \once \hideNotes
      f'8\3 \-
      \once \override TabNoteHead.parenthesized = ##t
      \once \override TabNoteHead.transparent = ##t
      f'4
    }
  >>
  d'1\3
}


\paper {
  system-system-spacing.minimum-distance = 20
}

\score {
  \new TabStaff \styleExample
  \layout {
    \guitarProStyleLayout
    indent = 0
  }
}

Reply via email to