From: Carl Sorensen Date: Sun, 31 Oct 2010 00:41:41 +0000 (-0600) Subject: Add tab-tie-follow-engraver X-Git-Tag: release/2.13.39-1~42 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=03075ddb8334c04774181dfa02313bac0f9bc03f;p=lilypond.git Add tab-tie-follow-engraver Based on the Scheme engraver in Marc Hohl's work. Simplified to acknowledge only ties and tab_note_heads --- diff --git a/lily/tab-tie-follow-engraver.cc b/lily/tab-tie-follow-engraver.cc new file mode 100644 index 0000000000..fbeb93266e --- /dev/null +++ b/lily/tab-tie-follow-engraver.cc @@ -0,0 +1,110 @@ +/* + This file is part of LilyPond, the GNU music typesetter. + + Copyright (C) 2010 Carl D. Sorensen + + LilyPond is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . +*/ + +#include +#include + +#include "engraver.hh" + +using namespace std; + +#include "context.hh" +#include "item.hh" + +#include "translator.icc" + +/* + Change tab-note-head properties for a note_head at the right end of a tie +*/ +class Tab_tie_follow_engraver : public Engraver +{ + vector ties_; + vector note_heads_; + +public: + TRANSLATOR_DECLARATIONS (Tab_tie_follow_engraver); + +protected: + DECLARE_ACKNOWLEDGER (tie); + DECLARE_ACKNOWLEDGER (tab_note_head); + void process_acknowledged (); + + void stop_translation_timestep (); +}; + +Tab_tie_follow_engraver::Tab_tie_follow_engraver () +{ +} + +void +Tab_tie_follow_engraver::acknowledge_tie (Grob_info info) +{ + ties_.push_back (info.grob ()); +} + +void +Tab_tie_follow_engraver::acknowledge_tab_note_head (Grob_info info) +{ + note_heads_.push_back (info.grob ()); +} + +void +Tab_tie_follow_engraver::process_acknowledged () +{ + if (ties_.size () && note_heads_.size ()) + { + SCM proc = ly_lily_module_constant ("ly:spanner-bound"); + for (vsize i = 0; i < ties_.size (); i++) + { + SCM right_bound = scm_call_2 (proc, + ties_[i]->self_scm (), + scm_from_int (RIGHT)); + + for (vsize k = 0; k < note_heads_.size (); k++) + if (right_bound == note_heads_[k]->self_scm ()) + note_heads_[k]->set_property ("tie-follow", SCM_BOOL_T); + } + } +} + +void +Tab_tie_follow_engraver::stop_translation_timestep () +{ + ties_.clear (); + note_heads_.clear(); +} + +ADD_ACKNOWLEDGER (Tab_tie_follow_engraver, tie); +ADD_ACKNOWLEDGER (Tab_tie_follow_engraver, tab_note_head); + +ADD_TRANSLATOR (Tab_tie_follow_engraver, + /* doc */ + "Adjust TabNoteHead properties when a tie is followed" + " by a slur or glissando.", + + /* create */ + " ", + + /* read */ + " ", + + /* write */ + " " + ); + diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly index 0b6cd7b3aa..c61d57062f 100644 --- a/ly/engraver-init.ly +++ b/ly/engraver-init.ly @@ -719,6 +719,7 @@ context." \alias "Voice" \consists "Tab_note_heads_engraver" \consists "Tab_harmonic_engraver" + \consists "Tab_tie_follow_engraver" \remove "Note_heads_engraver" \remove "Fingering_engraver" @@ -782,6 +783,7 @@ context." \override Hairpin #'transparent = ##t \override Script #'stencil = ##f \override TextScript #'stencil = ##f + \override Glissando #'stencil = #glissando::draw-tab-glissando %% 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) diff --git a/ly/property-init.ly b/ly/property-init.ly index b08c572497..3bed8193a3 100644 --- a/ly/property-init.ly +++ b/ly/property-init.ly @@ -453,6 +453,7 @@ tabFullNotation = { \revert TabVoice.MultiMeasureRestNumber #'transparent \revert TabVoice.MultiMeasureRestText #'transparent % markups etc. + \revert TabVoice.Glissando #'stencil \revert TabVoice.Script #'stencil \revert TabVoice.TextScript #'stencil \revert TabVoice.TextSpanner #'stencil diff --git a/scm/define-grob-interfaces.scm b/scm/define-grob-interfaces.scm index 22316b5886..e0bdf865ae 100644 --- a/scm/define-grob-interfaces.scm +++ b/scm/define-grob-interfaces.scm @@ -201,7 +201,7 @@ interesting enough to maintain a hara-kiri staff." (ly:add-interface 'tab-note-head-interface "A note head in tablature." - '(details)) + '(details tie-follow)) (ly:add-interface 'trill-spanner-interface diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index 4202b26b96..10309e2818 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -1061,6 +1061,9 @@ Internally used to distribute beam shortening over stems.") (system-Y-offset ,number? "The Y-offset (relative to the bottom of the top-margin of the page) of the system to which this staff belongs.") + (tie-follow ,boolean? "Indicates whether a note in tablature is tied to +another one.") + (use-breve-rest ,boolean? "Use breve rests for measures longer than a whole rest.") diff --git a/scm/tablature.scm b/scm/tablature.scm index 419f93c2cf..609e690e60 100644 --- a/scm/tablature.scm +++ b/scm/tablature.scm @@ -180,78 +180,113 @@ (define-public (tie::handle-tab-note-head grob) (let* ((original (ly:grob-original grob)) (tied-tab-note-head (ly:spanner-bound grob RIGHT)) + (tie-follow (ly:grob-property tied-tab-note-head 'tie-follow #f)) (siblings (if (ly:grob? original) (ly:spanner-broken-into original) '()))) - (if (and (>= (length siblings) 2) - (eq? (car (last-pair siblings)) grob)) - ;; tie is split -> get TabNoteHead #'details - (let* ((details (ly:grob-property tied-tab-note-head 'details)) - (tied-properties (assoc-get 'tied-properties details '())) - (tab-note-head-parenthesized (assoc-get 'parenthesize tied-properties #t)) - ;; we need the begin-of-line entry in the 'break-visibility vector - (tab-note-head-visible - (vector-ref (assoc-get 'break-visibility - tied-properties #(#f #f #t)) 2))) - - (if tab-note-head-visible - ;; tab note head is visible - (if tab-note-head-parenthesized - (ly:grob-set-property! tied-tab-note-head 'stencil - (lambda (grob) - (parenthesize-tab-note-head grob)))) - ;; tab note head is invisible - (begin - (ly:grob-set-property! tied-tab-note-head 'transparent #t) - (ly:grob-set-property! tied-tab-note-head 'whiteout #f)))) - - ;; tie is not split -> make fret number invisible - (begin - (ly:grob-set-property! tied-tab-note-head 'transparent #t) - (ly:grob-set-property! tied-tab-note-head 'whiteout #f))))) + (if tie-follow + ;; tab note head is right bound of a tie -> parenthesize it at all events + (ly:grob-set-property! tied-tab-note-head 'stencil + (lambda (grob) + (parenthesize-tab-note-head grob))) + ;; otherwise, check whether tie is split: + (if (and (>= (length siblings) 2) + (eq? (car (last-pair siblings)) grob)) + ;; tie is split -> get TabNoteHead #'details + (let* ((details (ly:grob-property tied-tab-note-head 'details)) + (tied-properties (assoc-get 'tied-properties details '())) + (tab-note-head-parenthesized (assoc-get 'parenthesize tied-properties #t)) + ;; we need the begin-of-line entry in the 'break-visibility vector + (tab-note-head-visible + (vector-ref (assoc-get 'break-visibility + tied-properties #(#f #f #t)) 2))) + + (if tab-note-head-visible + ;; tab note head is visible + (if tab-note-head-parenthesized + (ly:grob-set-property! tied-tab-note-head 'stencil + (lambda (grob) + (parenthesize-tab-note-head grob)))) + ;; tab note head is invisible + (ly:grob-set-property! tied-tab-note-head 'transparent #t))) + + ;; tie is not split + (ly:grob-set-property! tied-tab-note-head 'transparent #t))))) + + ;; repeat ties occur within alternatives in a repeat construct; ;; TabNoteHead #'details handles the appearance in this case (define-public (repeat-tie::handle-tab-note-head grob) (let* ((tied-tab-note-head (ly:grob-object grob 'note-head)) - (details (ly:grob-property tied-tab-note-head 'details)) - (repeat-tied-properties (assoc-get 'repeat-tied-properties details '())) - (tab-note-head-visible (assoc-get 'note-head-visible repeat-tied-properties #t)) - (tab-note-head-parenthesized (assoc-get 'parenthesize repeat-tied-properties #t))) - - (if tab-note-head-visible - ;; tab note head is visible - (if tab-note-head-parenthesized - (ly:grob-set-property! tied-tab-note-head 'stencil - (lambda (grob) - (parenthesize-tab-note-head grob)))) - ;; tab note head is invisible - (begin - (ly:grob-set-property! tied-tab-note-head 'transparent #t) - (ly:grob-set-property! tied-tab-note-head 'whiteout #f))))) + (tie-follow (ly:grob-property tied-tab-note-head 'tie-follow #f))) + (if tie-follow + ;; tab note head is right bound of a tie -> parenthesize it at all events + (ly:grob-set-property! tied-tab-note-head 'stencil + (lambda (grob) + (parenthesize-tab-note-head grob))) + ;; otherwise check 'details + (let* ((details (ly:grob-property tied-tab-note-head 'details)) + (repeat-tied-properties (assoc-get 'repeat-tied-properties details '())) + (tab-note-head-visible (assoc-get 'note-head-visible repeat-tied-properties #t)) + (tab-note-head-parenthesized (assoc-get 'parenthesize repeat-tied-properties #t))) + + (if tab-note-head-visible + ;; tab note head is visible + (if tab-note-head-parenthesized + (ly:grob-set-property! tied-tab-note-head 'stencil + (lambda (grob) + (parenthesize-tab-note-head grob)))) + ;; tab note head is invisible + (ly:grob-set-property! tied-tab-note-head 'transparent #t)))))) ;; the slurs should not be too far apart from the corresponding fret number, so -;; we move the slur towards the TabNoteHeads: +;; we move the slur towards the TabNoteHeads; moreover, if the left fret number is +;; the right-bound of a tie, we'll set it in parentheses: (define-public (slur::draw-tab-slur grob) ;; TODO: use a less "brute-force" method to decrease ;; the distance between the slur ends and the fret numbers - (let* ((staff-space (ly:staff-symbol-staff-space grob)) + (let* ((original (ly:grob-original grob)) + (left-bound (ly:spanner-bound original LEFT)) + (left-tab-note-head (ly:grob-property left-bound 'cause)) + (tie-follow (ly:grob-property left-tab-note-head 'tie-follow #f)) + (staff-space (ly:staff-symbol-staff-space grob)) (control-points (ly:grob-property grob 'control-points)) (new-control-points (map - (lambda (p) - (cons (car p) - (- (cdr p) - (* staff-space - (ly:grob-property grob 'direction) - 0.35)))) - control-points))) + (lambda (p) + (cons (car p) + (- (cdr p) + (* staff-space + (ly:grob-property grob 'direction) + 0.35)))) + control-points))) (ly:grob-set-property! grob 'control-points new-control-points) + (and tie-follow + (ly:grob-set-property! left-tab-note-head 'stencil + (lambda (grob) + (parenthesize-tab-note-head grob)))) (ly:slur::print grob))) +;; The glissando routine works similarly to the slur routine; if the +;; fret number is "tied to", it should become parenthesized. +(define-public (glissando::draw-tab-glissando grob) + (let* ((original (ly:grob-original grob)) + (left-tab-note-head (ly:spanner-bound original LEFT)) + (tie-follow (ly:grob-property left-tab-note-head 'tie-follow #f))) + + (and tie-follow + (ly:grob-set-property! left-tab-note-head 'stencil + (lambda (grob) + (parenthesize-tab-note-head grob))) + ;; increase left padding to avoid collision between + ;; closing parenthesis and glissando line + (ly:grob-set-nested-property! grob '(bound-details left padding) 0.75)) + (ly:line-spanner::print grob))) + ;; for \tabFullNotation, the stem tremolo beams are too big in comparison to ;; normal staves; this wrapper function scales accordingly: (define-public (stem-tremolo::calc-tab-width grob) (let ((width (ly:stem-tremolo::calc-width grob)) - (staff-space (ly:staff-symbol-staff-space grob))) + (staff-space (ly:staff-symbol-staff-space grob))) (/ width staff-space)))