summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Hohl <marc@hohlart.de>2009-07-10 10:53:06 +0200
committerCarl Sorensen <c_sorensen@byu.edu>2009-08-04 06:47:23 -0600
commit8f4004f8cd8c0902c5a9409a3cd75c519f22ef47 (patch)
tree025d154ebcf7cde265074792e237086b43aa4276
parent1a1d2e078682968b5a0a98ecbe2388b93fa2aa44 (diff)
New tablature features
this patch includes: 1) tablature is now "numbers only" as default 2) dead notes and palm mute is supported 3) "tied to" fret numbers become invisible (or parenthesized after line breaks or in a second volta) 4) the slope of glissando lines points in the right direction 5) grace notes (even parenthesized) are represented by smaller fret numbers.
-rw-r--r--input/regression/dead-notes.ly26
-rw-r--r--input/regression/modern-tab-clef-scaled.ly39
-rw-r--r--input/regression/modern-tab-clef.ly44
-rw-r--r--input/regression/palm-mute.ly27
-rw-r--r--input/regression/tablature-full-notation.ly36
-rw-r--r--input/regression/tablature-glissando.ly23
-rw-r--r--input/regression/tablature-grace-notes.ly24
-rw-r--r--input/regression/tablature-tie-behaviour.ly31
-rw-r--r--ly/engraver-init.ly40
-rw-r--r--ly/property-init.ly81
-rw-r--r--scm/lily.scm1
-rw-r--r--scm/music-functions.scm1
-rw-r--r--scm/output-lib.scm16
-rw-r--r--scm/parser-clef.scm7
-rw-r--r--scm/tablature.scm178
15 files changed, 556 insertions, 18 deletions
diff --git a/input/regression/dead-notes.ly b/input/regression/dead-notes.ly
new file mode 100644
index 0000000000..253fdd5bf3
--- /dev/null
+++ b/input/regression/dead-notes.ly
@@ -0,0 +1,26 @@
+\version "2.13.4"
+
+\header{ texidoc = "Muted notes (also called dead notes) are supported
+ within normal staves and tablature."
+ }
+
+deadnotes = \relative c,, {
+ e8. \deadNotesOn e16 \deadNotesOff g4 a b |
+ e8. \deadNote e16 g4 a b |
+ e,4. \deadNote { e8 e e } e4 |
+ < e, \deadNote b' e >8 < e \deadNote b' e > < e \deadNote b' e >4 < e \deadNote b' e >4 r
+ \bar "|."
+}
+
+\context StaffGroup <<
+ \context Staff <<
+ \clef "bass_8"
+ \deadnotes
+ >>
+ \context TabStaff <<
+ \set TabStaff.stringTunings = #bass-tuning
+ \deadnotes
+ >>
+>>
+
+
diff --git a/input/regression/modern-tab-clef-scaled.ly b/input/regression/modern-tab-clef-scaled.ly
new file mode 100644
index 0000000000..12caf11139
--- /dev/null
+++ b/input/regression/modern-tab-clef-scaled.ly
@@ -0,0 +1,39 @@
+\version "2.13.4"
+
+\header{ texidoc = "The sans serif style tab clef is automatically adjusted to
+ different string spacings."
+ }
+
+guitar = \relative c {
+ c4 d e f
+ e4 d c2
+}
+
+\score {
+ <<
+ \new Staff {
+ \clef "treble_8"
+ \guitar
+ }
+ \new TabStaff {
+ \clef "moderntab"
+ \set TabStaff.stringTunings = #guitar-tuning
+ \guitar
+ }
+ >>
+}
+
+\score {
+ <<
+ \new Staff {
+ \clef "treble_8"
+ \guitar
+ }
+ \new TabStaff {
+ \clef "moderntab"
+ \set TabStaff.stringTunings = #guitar-tuning
+ \override TabStaff.StaffSymbol #'staff-space = #1.0 % default value is 1.5
+ \guitar
+ }
+ >>
+} \ No newline at end of file
diff --git a/input/regression/modern-tab-clef.ly b/input/regression/modern-tab-clef.ly
new file mode 100644
index 0000000000..d95fb23bcb
--- /dev/null
+++ b/input/regression/modern-tab-clef.ly
@@ -0,0 +1,44 @@
+\version "2.13.4"
+
+\header{ texidoc = "Sans serif style tab clefs are supported by @code{\\clef moderntab}.
+ This alternative clef supports four- to seven-stringed instruments
+ and is scaled automatically."
+ }
+
+bass = \relative c, {
+ c4 d e f
+ e4 d c2
+}
+
+guitar = \relative c {
+ c4 d e f
+ e4 d c2
+}
+
+\score {
+ <<
+ \new Staff {
+ \clef "bass_8"
+ \bass
+ }
+ \new TabStaff {
+ \clef "moderntab"
+ \set TabStaff.stringTunings = #bass-four-string-tuning
+ \bass
+ }
+ >>
+}
+
+\score {
+ <<
+ \new Staff {
+ \clef "treble_8"
+ \guitar
+ }
+ \new TabStaff {
+ \clef "moderntab"
+ \set TabStaff.stringTunings = #guitar-seven-string-tuning
+ \guitar
+ }
+ >>
+} \ No newline at end of file
diff --git a/input/regression/palm-mute.ly b/input/regression/palm-mute.ly
new file mode 100644
index 0000000000..33123f3f8e
--- /dev/null
+++ b/input/regression/palm-mute.ly
@@ -0,0 +1,27 @@
+\version "2.13.4"
+
+\header{ texidoc = "The palm mute technique for stringed instruments
+ is supported by triangle-shaped note heads."
+ }
+
+palmmute = \relative c, {
+ \time 4/4
+ e8^\markup { \musicglyph #"noteheads.u2do" = palm mute }
+ \palmMuteOn e e \palmMuteOff e e \palmMute e e e |
+ e8 \palmMute { e e e } e e e e |
+ \palmMuteOn < e b' e >8 e e e < e b' e >2 \palmMuteOff |
+ < \palmMute e b' e >8 \palmMute { e e e } < \palmMute e b' e >2
+ \bar "|."
+}
+
+\context StaffGroup <<
+ \context Staff <<
+ \clef "G_8"
+ \palmmute
+ >>
+ \context TabStaff <<
+ \palmmute
+ >>
+>>
+
+
diff --git a/input/regression/tablature-full-notation.ly b/input/regression/tablature-full-notation.ly
new file mode 100644
index 0000000000..80a48688be
--- /dev/null
+++ b/input/regression/tablature-full-notation.ly
@@ -0,0 +1,36 @@
+\version "2.13.4"
+
+\header{ texidoc = "As default, tablature staves show only the fret numbers, because
+ in most situations, they are combined with normal staves.
+ When used without standard notation, @code{tabFullNotation}
+ can be used."
+ }
+
+tabstuff = {
+ \time 3/4
+ c4^"test" d( e)
+ f4\f g a^\fermata
+ c8\<\( c16 c ~ c2\!
+ c'2.\)
+ \mark \default
+ R2.
+ r4 d4 r8 e
+ \times 3/4 { b4 c \glissando d\5 \glissando c }
+ c4. d-_( e\varcoda)
+ ->f g~ a\prall g\thumb e-.
+ \bar "|."
+}
+
+\score {
+ <<
+ \new Staff { \clef "G_8" \tabstuff }
+ \new TabStaff { \tabstuff }
+ >>
+}
+
+\score {
+ \new TabStaff {
+ \tabFullNotation
+ \tabstuff
+ }
+}
diff --git a/input/regression/tablature-glissando.ly b/input/regression/tablature-glissando.ly
new file mode 100644
index 0000000000..17db67a307
--- /dev/null
+++ b/input/regression/tablature-glissando.ly
@@ -0,0 +1,23 @@
+\version "2.13.4"
+
+\header{ texidoc = "Glissando lines in tablature have the right slope."
+ }
+
+\paper { ragged-right = ##f } % strech the staff to make glissando lines visible
+
+glissandotest = \relative c {
+ c4\5 \glissando d\5 \glissando e\5 f\5 |
+ c4\5 \glissando d\5 \glissando c2\5 |
+ c4\5 \glissando c'\4 c\4 \glissando c,\5
+ \bar "|."
+}
+
+\context StaffGroup <<
+ \context Staff <<
+ \clef "G_8"
+ \glissandotest
+ >>
+ \context TabStaff <<
+ \glissandotest
+ >>
+>>
diff --git a/input/regression/tablature-grace-notes.ly b/input/regression/tablature-grace-notes.ly
new file mode 100644
index 0000000000..5012ddd643
--- /dev/null
+++ b/input/regression/tablature-grace-notes.ly
@@ -0,0 +1,24 @@
+\version "2.13.4"
+
+\header{ texidoc = "Fret numbers belonging to grace notes are smaller."
+ }
+
+gracenotes = \relative c {
+ c4 d e f
+ \grace e8 c4 d e f
+ \grace \parenthesize e8 c4 d e f
+ \appoggiatura e8 c4 d e f
+ \acciaccatura e8 c4 d e f
+ \bar "|."
+}
+
+\context StaffGroup <<
+ \context Staff <<
+ \clef "G_8"
+ \gracenotes
+ >>
+ \context TabStaff <<
+ \gracenotes
+ >>
+>>
+
diff --git a/input/regression/tablature-tie-behaviour.ly b/input/regression/tablature-tie-behaviour.ly
new file mode 100644
index 0000000000..8760c9f204
--- /dev/null
+++ b/input/regression/tablature-tie-behaviour.ly
@@ -0,0 +1,31 @@
+\version "2.13.4"
+
+\header{ texidoc = "In tablature, notes that are tied to are invisible
+ except after a line break or within a second volta;
+ here, the fret number is displayed in parentheses."
+ }
+
+tietest = \relative c {
+ \override Voice.StringNumber #'transparent = ##t % remove circled string numbers
+ \repeat volta 2 {
+ f2 ~ f4 e
+ g8 g ~ g g ~ g g~ g g ~
+ g1
+ c1 ~ \break c2 ~ c
+ < c\3 e\2 g\1 >4 < c\3 e\2 g\1 > ~ < c\3 e\2 g\1 >\laissezVibrer r
+ c4. d8 e2 ~
+ }
+ \alternative { { e2 r } { e2\repeatTie e2^\fermata } }
+ \bar "|."
+}
+
+\context StaffGroup <<
+ \context Staff <<
+ \clef "G_8"
+ \tietest
+ >>
+ \context TabStaff <<
+ \tietest
+ >>
+>>
+
diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly
index 9d19e92cdb..348d1a8c47 100644
--- a/ly/engraver-init.ly
+++ b/ly/engraver-init.ly
@@ -628,6 +628,7 @@ automatically when an output definition (a @code{\score} or
(Voice Stem direction ,UP)
(Voice Stem font-size -3)
(Voice NoteHead font-size -3)
+ (Voice TabNoteHead font-size -4)
(Voice Dots font-size -3)
(Voice Stem length-fraction 0.8)
(Voice Stem no-stem-extend #t)
@@ -716,12 +717,39 @@ context."
%% No accidental in tablature !
\remove "Accidental_engraver"
-
- \override Glissando #'extra-dy = #0.75
+ %% remove stems, beams, dots and rests ...
+ \override Stem #'stencil = ##f
+ \override Beam #'stencil = ##f
+ \override Dots #'stencil = ##f
+ \override Rest #'stencil = ##f
+ \override MultiMeasureRest #'stencil = ##f
+ %% ... all kinds of ties/slurs
+ \override Tie #'stencil = ##f
+ \override RepeatTie #'stencil = ##f
+ \override LaissezVibrerTie #'stencil = ##f
+ \override Slur #'stencil = ##f
+ \override PhrasingSlur #'stencil = ##f
+ %% 'tied to' fret numbers become invisible or parenthesized, respectively)
+ \override Tie #'after-line-breaking = #tie::handle-tab-tie
+ \override RepeatTie #'after-line-breaking = #repeat-tie::parenthesize-tab-note-head
+ %% ... and all kinds of markups, spanners etc.
+ \override TupletBracket #'stencil = ##f
+ \override TupletNumber #'stencil = ##f
+ \override DynamicText #'transparent = ##t
+ \override DynamicTextSpanner #'stencil = ##f
+ \override TextSpanner #'stencil = ##f
+ \override Hairpin #'transparent = ##t
+ \override Script #'stencil = ##f
+ \override TextScript #'stencil = ##f
+ %% the direction for glissando lines will be automatically corrected
+ \override Glissando #'extra-dy = #glissando::calc-tab-extra-dy
\override Glissando #'bound-details #'right = #`((attach-dir . ,LEFT)
(padding . 0.3))
\override Glissando #'bound-details #'left = #`((attach-dir . ,RIGHT)
(padding . 0.3))
+ %% dead notes
+ \override TabNoteHead #'glyph-name = #tab-note-head::calc-glyph-name
+ \override TabNoteHead #'stencil = #tab-note-head::whiteout-if-style-set
}
\context {
@@ -746,6 +774,14 @@ context."
\remove "Accidental_engraver"
\remove "Key_engraver"
\remove "String_number_engraver"
+ %% the clef handler
+ \override Clef #'stencil = #clef::print-modern-tab-if-set
+ %% no time signature
+ \override TimeSignature #'stencil = ##f
+ %% better parentheses in a TabStaff
+ \override ParenthesesItem #'stencils = #parentheses-item::calc-tabstaff-parenthesis-stencils
+ %% no arpeggios
+ \override Arpeggio #'stencil = ##f
%% Special "TAB" clef
clefGlyph = #"clefs.tab"
clefPosition = #0
diff --git a/ly/property-init.ly b/ly/property-init.ly
index fd5c766ef7..f91c4b8d85 100644
--- a/ly/property-init.ly
+++ b/ly/property-init.ly
@@ -420,3 +420,84 @@ pointAndClickOff = #(define-music-function (parser location) ()
pointAndClickOn = #(define-music-function (parser location) ()
(ly:set-option 'point-and-click #t)
(make-music 'SequentialMusic 'void #t))
+
+palmMuteOn = {
+ \override NoteHead #'style = #'do
+}
+
+palmMuteOff = {
+ \revert NoteHead #'style
+}
+
+palmMute =
+#(define-music-function (parser location note) (ly:music?)
+ ;; are we inside a <...>?
+ (if (eq? (ly:music-property note 'name) 'NoteEvent)
+ ;; yes -> add a tweak
+ (begin (set! (ly:music-property note 'tweaks)
+ (acons 'style 'do (ly:music-property note 'tweaks)))
+ note)
+ ;; no -> use predefined commands to switch to triangle-shaped note heads
+ #{
+ \palmMuteOn
+ $note
+ \palmMuteOff
+ #}))
+
+deadNotesOn = {
+ \override TabNoteHead #'style = #'cross
+ \override NoteHead #'style = #'cross
+}
+
+deadNotesOff = {
+ \revert TabNoteHead #'style
+ \revert NoteHead #'style
+}
+
+deadNote =
+#(define-music-function (parser location note) (ly:music?)
+ ;; are we inside a <...>?
+ (if (eq? (ly:music-property note 'name) 'NoteEvent)
+ ;; yes -> add a tweak
+ (begin (set! (ly:music-property note 'tweaks)
+ (acons 'style 'cross (ly:music-property note 'tweaks)))
+ note)
+ ;; no -> use predefined commmands for changing
+ ;; note head and tablature fret signs
+ #{
+ \deadNotesOn
+ $note
+ \deadNotesOff
+ #}))
+
+tabFullNotation = {
+ % time signature
+ \revert TabStaff.TimeSignature #'stencil
+ % stems (the half note gets a double stem)
+ \override TabVoice.Stem #'stencil = #tabvoice::draw-double-stem-for-half-notes
+ % beams, dots
+ \revert TabVoice.Beam #'stencil
+ \revert TabVoice.Dots #'stencil
+ \revert TabVoice.Tie #'stencil
+ \revert TabVoice.Tie #'after-line-breaking
+ \revert TabVoice.RepeatTie #'stencil
+ \revert TabVoice.RepeatTie #'after-line-braking
+ \revert TabVoice.LaissezVibrerTie #'stencil
+ \revert TabVoice.Slur #'stencil
+ \revert PhrasingSlur #'stencil
+ % tuplet stuff
+ \revert TabVoice.TupletBracket #'stencil
+ \revert TabVoice.TupletNumber #'stencil
+ % dynamic signs
+ \revert DynamicText #'transparent
+ \revert DynamicTextSpanner #'stencil
+ \revert TabVoice.DynamicTextSpanner #'stencil
+ \revert TabVoice.Hairpin #'transparent
+ % rests
+ \revert TabVoice.Rest #'stencil
+ \revert TabVoice.MultiMeasureRest #'stencil
+ % markups etc.
+ \revert TabVoice.Script #'stencil
+ \revert TabVoice.TextScript #'stencil
+ \revert TabStaff.Arpeggio #'stencil
+}
diff --git a/scm/lily.scm b/scm/lily.scm
index 7aa8c05c20..783679ca04 100644
--- a/scm/lily.scm
+++ b/scm/lily.scm
@@ -397,6 +397,7 @@ LilyPond safe mode. The syntax is the same as `define*-public'."
"paper.scm"
"backend-library.scm"
"x11-color.scm"
+ "tablature.scm"
;; must be after everything has been defined
"safe-lily.scm"))
diff --git a/scm/music-functions.scm b/scm/music-functions.scm
index c5e6f2da01..1372a15a52 100644
--- a/scm/music-functions.scm
+++ b/scm/music-functions.scm
@@ -384,6 +384,7 @@ i.e. this is not an override"
;; TODO: take this from voicedGraceSettings or similar.
'((Voice Stem font-size -3)
(Voice NoteHead font-size -3)
+ (Voice TabNoteHead font-size -4)
(Voice Dots font-size -3)
(Voice Stem length-fraction 0.8)
(Voice Stem no-stem-extend #t)
diff --git a/scm/output-lib.scm b/scm/output-lib.scm
index f9b920f37d..db1181f740 100644
--- a/scm/output-lib.scm
+++ b/scm/output-lib.scm
@@ -89,22 +89,6 @@
))
-; default tunings for common string instruments
-(define-public guitar-tuning '(4 -1 -5 -10 -15 -20))
-(define-public guitar-open-g-tuning '(2 -1 -5 -10 -17 -22))
-(define-public bass-tuning '(-17 -22 -27 -32))
-(define-public mandolin-tuning '(16 9 2 -5))
-
-;; tunings for 5-string banjo
-(define-public banjo-open-g-tuning '(2 -1 -5 -10 7))
-(define-public banjo-c-tuning '(2 -1 -5 -12 7))
-(define-public banjo-modal-tuning '(2 0 -5 -10 7))
-(define-public banjo-open-d-tuning '(2 -3 -6 -10 9))
-(define-public banjo-open-dm-tuning '(2 -3 -6 -10 9))
-;; convert 5-string banjo tuning to 4-string by removing the 5th string
-(define-public (four-string-banjo tuning)
- (reverse (cdr (reverse tuning))))
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; note heads
diff --git a/scm/parser-clef.scm b/scm/parser-clef.scm
index fff8f1b83d..a6d178eaef 100644
--- a/scm/parser-clef.scm
+++ b/scm/parser-clef.scm
@@ -132,3 +132,10 @@
(sort (map car supported-clefs) string<?)))
(make-music 'Music)))))
+;; a function to add new clefs at runtime
+(define-public (add-new-clef clef-name clef-glyph clef-position octavation c0-position)
+ "Append the entries for a clef symbol to supported clefs and c0-pitch-alist"
+ (set! supported-clefs
+ (acons clef-name (list clef-glyph clef-position octavation) supported-clefs))
+ (set! c0-pitch-alist
+ (acons clef-glyph c0-position c0-pitch-alist)))
diff --git a/scm/tablature.scm b/scm/tablature.scm
new file mode 100644
index 0000000000..3d92e76d65
--- /dev/null
+++ b/scm/tablature.scm
@@ -0,0 +1,178 @@
+;;;; tablature.scm
+;;;;
+;;;; source file of the GNU LilyPond music typesetter
+;;;;
+;;;; (c) 2009 Marc Hohl <marc@hohlart.de>
+
+;; default tunings for common string instruments
+;; guitar tunings
+(define-public guitar-tuning '(4 -1 -5 -10 -15 -20))
+(define-public guitar-seven-string-tuning '(4 -1 -5 -10 -15 -20 -25))
+(define-public guitar-drop-d-tuning '(4 -1 -5 -10 -15 -22))
+(define-public guitar-open-g-tuning '(2 -1 -5 -10 -17 -22))
+;; bass tunings
+(define-public bass-tuning '(-17 -22 -27 -32))
+(define-public bass-four-string-tuning '(-17 -22 -27 -32))
+(define-public bass-drop-d-tuning '(-17 -22 -27 -34))
+(define-public bass-five-string-tuning '(-17 -22 -27 -32 -37))
+(define-public bass-six-string-tuning '(-12 -17 -22 -27 -32 -37))
+;; mandolin
+(define-public mandolin-tuning '(16 9 2 -5))
+;; tunings for 5-string banjo
+(define-public banjo-open-g-tuning '(2 -1 -5 -10 7))
+(define-public banjo-c-tuning '(2 -1 -5 -12 7))
+(define-public banjo-modal-tuning '(2 0 -5 -10 7))
+(define-public banjo-open-d-tuning '(2 -3 -6 -10 9))
+(define-public banjo-open-dm-tuning '(2 -3 -6 -10 9))
+;; convert 5-string banjo tuning to 4-string by removing the 5th string
+(define-public (four-string-banjo tuning)
+ (reverse (cdr (reverse tuning))))
+
+;; for more control over glyph-name calculations,
+;; we use a custom callback for tab noteheads
+;; which will ignore 'style = 'do
+(define-public (tab-note-head::calc-glyph-name grob)
+ (let ((style (ly:grob-property grob 'style)))
+ (case style
+ ((cross) "2cross"))))
+
+;; ensure we only call notehead callback when
+;; 'style = 'cross
+(define-public (tab-note-head::whiteout-if-style-set grob)
+ (let ((style (ly:grob-property grob 'style)))
+ (if (and (symbol? style)
+ (eq? style 'cross))
+ (stencil-whiteout (ly:note-head::print grob))
+ (ly:text-interface::print grob))))
+
+;; definitions for the "moderntab" clef:
+;; the "moderntab" clef will be added to the list of known clefs,
+;; so it can be used as any other clef: \clef "moderntab"
+(add-new-clef "moderntab" "markup.moderntab" 0 0 0)
+
+;; define sans serif-style tab-Clefs as a markup:
+(define-builtin-markup-command (customTabClef layout props num-strings staff-space)
+ (integer? number?)
+ music
+ ()
+ "Draw a tab clef sans-serif style."
+ (define (square x) (* x x))
+ (let* ((scale-factor (/ staff-space 1.5))
+ (font-size (- (* num-strings 1.5 scale-factor) 7))
+ (base-skip (* (square (+ (* num-strings 0.195) 0.4)) scale-factor)))
+
+ (interpret-markup layout props
+ (markup #:vcenter #:bold
+ #:override (cons 'font-family 'sans)
+ #:fontsize font-size
+ #:override (cons 'baseline-skip base-skip)
+ #:left-align #:center-column ("T" "A" "B")))))
+
+;; this function decides which clef to take
+(define-public (clef::print-modern-tab-if-set grob)
+ (let ((glyph (ly:grob-property grob 'glyph)))
+ ;; which clef is wanted?
+ (if (string=? glyph "markup.moderntab")
+ ;; if it is "moderntab", we'll draw it
+ (let* ((staff-symbol (ly:grob-object grob 'staff-symbol))
+ (line-count (ly:grob-property staff-symbol 'line-count))
+ (staff-space (ly:grob-property staff-symbol 'staff-space 1)))
+ (grob-interpret-markup grob (make-customTabClef-markup line-count staff-space)))
+ ;; otherwise, we simply use the default printing routine
+ (ly:clef::print grob))))
+
+;; if stems are drawn, it is nice to have a double stem for
+;; (dotted) half notes to distinguish them from quarter notes:
+(define-public (tabvoice::draw-double-stem-for-half-notes grob)
+ (let ((stem (ly:stem::print grob)))
+
+ ;; is the note a (dotted) half note?
+ (if (= 1 (ly:grob-property grob 'duration-log))
+ ;; yes -> draw double stem
+ (ly:stencil-combine-at-edge stem X RIGHT stem 0.5)
+ ;; no -> draw simple stem
+ stem)))
+
+;; as default, the glissando line between fret numbers goes
+;; upwards, here we have a function to correct this behavior:
+(define-public (glissando::calc-tab-extra-dy grob)
+ (let* ((original (ly:grob-original grob))
+ (left-bound (ly:spanner-bound original LEFT))
+ (right-bound (ly:spanner-bound original RIGHT))
+ (left-pitch (ly:event-property (event-cause left-bound) 'pitch))
+ (right-pitch (ly:event-property (event-cause right-bound) 'pitch)))
+
+ (if (< (ly:pitch-semitones right-pitch) (ly:pitch-semitones left-pitch))
+ -0.75
+ 0.75)))
+
+;; for ties in tablature, fret numbers that are tied to should be invisible,
+;; except for 'tied to' numbers after a line break;; these will be
+;; parenthesized (thanks to Neil for his solution):
+(define-public (parenthesize-tab-note-head grob)
+ ;; Helper function to parenthesize tab noteheads,
+ ;; since we can't use ParenthesesItem at this stage
+ ;; This is basically the same as the C++ function
+ ;; in accidental.cc, converted to Scheme
+ (let* ((font (ly:grob-default-font grob))
+ (open (stencil-whiteout
+ (ly:font-get-glyph font "accidentals.leftparen")))
+ (close (stencil-whiteout
+ (ly:font-get-glyph font "accidentals.rightparen")))
+ (me (ly:text-interface::print grob)))
+ (ly:stencil-combine-at-edge
+ (ly:stencil-combine-at-edge
+ me
+ X
+ LEFT
+ open)
+ X
+ RIGHT
+ close)))
+
+;; ParenthesesItem doesn't work very well for TabNoteHead, since
+;; the parentheses are too small and clash with the staff-lines
+;; Define a callback for the 'stencils property which will tweak
+;; the parentheses' appearance for TabNoteHead
+(define-public (parentheses-item::calc-tabstaff-parenthesis-stencils grob)
+ ;; the grob we want to parenthesize
+ (let ((victim (ly:grob-array-ref (ly:grob-object grob 'elements) 0)))
+ ;; check whether it's a notehead
+ (if (grob::has-interface victim 'note-head-interface)
+ (begin
+ ;; tweak appearance before retrieving
+ ;; list of stencils '(left-paren right-paren)
+ ;; get the font-size from victim (=TabNoteHead) to handle
+ ;; grace notes properly
+ (ly:grob-set-property! grob 'font-size
+ (ly:grob-property victim 'font-size))
+ (ly:grob-set-property! grob 'padding 0)
+ ;; apply whiteout to each element of the list
+ (map stencil-whiteout
+ (parentheses-item::calc-parenthesis-stencils grob)))
+ (parentheses-item::calc-parenthesis-stencils grob))))
+
+;; the handler for ties in tablature;; split ties yield in a parenthesized
+;; fret number, otherwise the fret number will be invisible.
+(define-public (tie::handle-tab-tie grob)
+ (let* ((original (ly:grob-original grob))
+ (tied-tab-note-head (ly:spanner-bound grob RIGHT))
+ (siblings (if (ly:grob? original)
+ (ly:spanner-broken-into original) '())))
+
+ (if (and (>= (length siblings) 2)
+ (eq? (car (last-pair siblings)) grob))
+ ;; tie is split -> parenthesize
+ (ly:grob-set-property! tied-tab-note-head 'stencil
+ (lambda (grob) (parenthesize-tab-note-head grob)))
+
+ ;; tie is not split -> make fret number invisible
+ (ly:grob-set-property! tied-tab-note-head 'transparent #t))))
+
+;; repeat ties occur within alternatives in a repeat construct;
+;; the correspondig fret numbers are shown in parentheses:
+(define-public (repeat-tie::parenthesize-tab-note-head grob)
+ (let ((tied-tab-note-head (ly:grob-object grob 'note-head)))
+
+ (ly:grob-set-property! tied-tab-note-head 'stencil
+ (lambda (grob) (parenthesize-tab-note-head grob))))) \ No newline at end of file