Am Do., 15. Aug. 2024 um 16:13 Uhr schrieb Thomas Morley <
[email protected]>:
>
> 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
}
}