]> git.donarmstrong.com Git - lilypond.git/commitdiff
Add tab-tie-follow-engraver
authorCarl Sorensen <c_sorensen@byu.edu>
Sun, 31 Oct 2010 00:41:41 +0000 (18:41 -0600)
committerCarl Sorensen <c_sorensen@byu.edu>
Wed, 3 Nov 2010 14:10:04 +0000 (08:10 -0600)
Based on the Scheme engraver in Marc Hohl's work.
Simplified to acknowledge only ties and tab_note_heads

lily/tab-tie-follow-engraver.cc [new file with mode: 0644]
ly/engraver-init.ly
ly/property-init.ly
scm/define-grob-interfaces.scm
scm/define-grob-properties.scm
scm/tablature.scm

diff --git a/lily/tab-tie-follow-engraver.cc b/lily/tab-tie-follow-engraver.cc
new file mode 100644 (file)
index 0000000..fbeb932
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <cctype>
+#include <cstdio>
+
+#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<Grob*> ties_;
+  vector<Grob*> 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 */
+                " "
+                );
+
index 0b6cd7b3aa68fc1dbda2aff660eb160553b9083a..c61d57062f637f0bc04e3930d6b37d22a05e7fcb 100644 (file)
@@ -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)
index b08c572497740bcf0cc3aae7f048f01304b69915..3bed8193a37f6d968010c49637deb6aa62775bbf 100644 (file)
@@ -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
index 22316b5886f760532ba7bba88ad8aa8e25c2aea3..e0bdf865ae759d9c2126bac5230a7fe2112fc6c5 100644 (file)
@@ -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
index 4202b26b96080da12ae992b1da4338808cac8e30..10309e28185abe738c5de95acf5f63be290ef78a 100644 (file)
@@ -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.")
 
index 419f93c2cf15012ba6e3deedfc915b4c5ee48dc1..609e690e6011aa78a97f9611122550732a80091a 100644 (file)
 (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)))