From 75eedccb2b2b26abab05240d8943e8e2198c76f9 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Fri, 8 Dec 2006 15:58:48 +0100 Subject: [PATCH] use angle brackets for harmonic notes in tablature. --- lily/tab-harmonic-engraver.cc | 73 +++++++++++++++++++++++++++++++ ly/engraver-init.ly | 2 + scm/define-grob-properties.scm | 1 + scm/define-grobs.scm | 12 +++++- scm/define-markup-commands.scm | 12 +----- scm/output-lib.scm | 79 ++++++++++++++++++++++++++++------ scm/stencil.scm | 21 ++++++++- 7 files changed, 173 insertions(+), 27 deletions(-) create mode 100644 lily/tab-harmonic-engraver.cc diff --git a/lily/tab-harmonic-engraver.cc b/lily/tab-harmonic-engraver.cc new file mode 100644 index 0000000000..385b462cbd --- /dev/null +++ b/lily/tab-harmonic-engraver.cc @@ -0,0 +1,73 @@ +/* + tab-harmonic-engraver.cc -- implement Tab_harmonic_engraver + + source file of the GNU LilyPond music typesetter + + (c) 2005--2006 Han-Wen Nienhuys + +*/ + +#include "engraver.hh" + +#include "item.hh" +#include "pointer-group-interface.hh" +#include "simple-closure.hh" +#include "stream-event.hh" +#include "warn.hh" + +#include "translator.icc" + +class Tab_harmonic_engraver : public Engraver +{ + TRANSLATOR_DECLARATIONS (Tab_harmonic_engraver); + +protected: + DECLARE_ACKNOWLEDGER (note_head); +}; + +Tab_harmonic_engraver::Tab_harmonic_engraver() +{ +} + +void +Tab_harmonic_engraver::acknowledge_note_head (Grob_info info) +{ + if (Stream_event *note = info.event_cause ()) + { + for (SCM s = note->get_property ("articulations"); + scm_is_pair (s); s = scm_cdr (s)) + { + Stream_event *ev = unsmob_stream_event (scm_car (s)); + + if (!ev) + continue; + + + if (ev->in_event_class ("harmonic-event")) + { + if (Item *victim = info.item ()) + { + Engraver *eng = dynamic_cast (info.origin_translator ()); + Item *paren = eng->make_item ("HarmonicParenthesesItem", victim->self_scm ()); + Pointer_group_interface::add_grob (paren, ly_symbol2scm ("elements"), victim); + + paren->set_parent (victim, Y_AXIS); + + Real size = robust_scm2double (paren->get_property ("font-size"), 0.0) + + robust_scm2double (victim->get_property ("font-size"), 0.0); + paren->set_property ("font-size", scm_from_double (size)); + } + } + } + } +} + +ADD_ACKNOWLEDGER (Tab_harmonic_engraver, note_head); +ADD_TRANSLATOR (Tab_harmonic_engraver, + /* doc */ "Parenthesize objects whose music cause has the @code{parenthesize} " + "property.", + + /* create */ + "HarmonicParenthesesItem ", + /* read */ "", + /* write */ ""); diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly index 6461352d30..938a0c856e 100644 --- a/ly/engraver-init.ly +++ b/ly/engraver-init.ly @@ -653,6 +653,8 @@ AncientRemoveEmptyStaffContext = \context { \name "TabVoice" \alias "Voice" \consists "Tab_note_heads_engraver" + \consists "Tab_harmonic_engraver" + \remove "Note_heads_engraver" \remove "Fingering_engraver" \remove "New_fingering_engraver" diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index 0081da0636..9d0d665b88 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -374,6 +374,7 @@ stems that are placed in tight configurations. For opposite directions, this amount is the correction for two normal sized stems that overlap completely.") (stencil ,ly:stencil? "The symbol to print.") + (stencils ,list? "Multiple stencils, used as intermediate value.") (strict-note-spacing ,boolean? "If set, unbroken columns with non-musical material (clefs, barlines, etc.) are not spaced separately, but put before musical columns.") diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm index 4b70e8428a..7ae81380f7 100644 --- a/scm/define-grobs.scm +++ b/scm/define-grobs.scm @@ -1184,11 +1184,20 @@ (ParenthesesItem . ((stencil . ,parentheses-item::print) + (stencils . ,parentheses-item::calc-parenthesis-stencils) (font-size . -6) (padding . 0.2) (meta . ((class . Item) (interfaces . (parentheses-interface font-interface)))) )) + + (HarmonicParenthesesItem + . ((stencil . ,parentheses-item::print) + (padding . 0) + (stencils . ,parentheses-item::calc-angled-bracket-stencils) + (meta . ((class . Item) + (interfaces . (parentheses-interface font-interface)))) + )) (PhrasingSlur . ((details . ,default-slur-details) @@ -1711,11 +1720,12 @@ (interfaces . (side-position-interface system-start-delimiter-interface)))))) - (TabNoteHead . ( (stencil . ,ly:text-interface::print) (Y-offset . ,ly:staff-symbol-referencer::callback) + (X-offset . ,ly:self-alignment-interface::x-aligned-on-self) + (direction . 0) (font-size . -2) (stem-attachment . (0.0 . 1.35)) (font-series . bold) diff --git a/scm/define-markup-commands.scm b/scm/define-markup-commands.scm index 25ced26a9b..5d96ecb179 100644 --- a/scm/define-markup-commands.scm +++ b/scm/define-markup-commands.scm @@ -127,17 +127,7 @@ circle of diameter 0 (ie sharp corners)." (define-markup-command (whiteout layout props arg) (markup?) "Provide a white underground for @var{arg}" - (let* ((stil (interpret-markup layout props arg)) - (white - (interpret-markup layout props - (make-with-color-markup - white - (make-filled-box-markup - (ly:stencil-extent stil X) - (ly:stencil-extent stil Y) - 0.0))))) - - (ly:stencil-add white stil))) + (stencil-whiteout (interpret-markup layout props arg))) (define-markup-command (pad-markup layout props padding arg) (number? markup?) "Add space around a markup object." diff --git a/scm/output-lib.scm b/scm/output-lib.scm index 88904384cd..9075abd86f 100644 --- a/scm/output-lib.scm +++ b/scm/output-lib.scm @@ -55,14 +55,28 @@ ;; The TabNoteHead tablatureFormat callback. ;; Compute the text grob-property -(define-public (fret-number-tablature-format string tuning pitch) - (make-whiteout-markup - (make-vcenter-markup - (number->string - (- (ly:pitch-semitones pitch) - (list-ref tuning - ;; remove 1 because list index starts at 0 and guitar string at 1. - (- string 1))))))) +(define-public (fret-number-tablature-format string + context event) + (let* + ((tuning (ly:context-property context 'stringTunings)) + (pitch (ly:event-property event 'pitch)) + (is-harmonic (apply + functional-or + (map + (lambda (ev) + (eq? 'harmonic-event (ly:event-property ev 'class))) + (ly:event-property event 'articulations))))) + + + (make-whiteout-markup + (make-vcenter-markup + (format + "~a" + (- (ly:pitch-semitones pitch) + (list-ref tuning + ;; remove 1 because list index starts at 0 and guitar string at 1. + (- string 1)))))) + )) ;; The 5-string banjo has got a extra string, the fifth (duh), wich ;; starts at the fifth fret on the neck. Frets on the fifth string @@ -70,14 +84,20 @@ ;; the "first fret" on the fifth string is really the sixth fret ;; on the banjo neck. ;; We solve this by defining a new fret-number-tablature function: -(define-public (fret-number-tablature-format-banjo string tuning pitch) +(define-public (fret-number-tablature-format-banjo string + context event) + (let* + ((tuning (ly:context-property context 'stringTuning)) + (pitch (ly:event-property event 'pitch)) + ) (make-whiteout-markup (make-vcenter-markup (let ((fret (- (ly:pitch-semitones pitch) (list-ref tuning (- string 1))))) (number->string (cond ((and (> fret 0) (= string 5)) (+ fret 5)) - (else fret))))))) + (else fret)))))) + )) ; default tunings for common string instruments @@ -285,6 +305,37 @@ centered, X==1 is at the right, X == -1 is at the left." ;; * Pitch Trill Heads ;; * Parentheses +(define-public (parentheses-item::calc-parenthesis-stencils grob) + (let* ( + (font (ly:grob-default-font grob)) + (lp (ly:font-get-glyph font "accidentals.leftparen")) + (rp (ly:font-get-glyph font "accidentals.rightparen")) + ) + + (list lp rp))) + + +(define (grob-text grob text) + (let* + ((layout (ly:grob-layout grob)) + (defs (ly:output-def-lookup layout 'text-font-defaults)) + (props (ly:grob-alist-chain grob defs))) + + (ly:text-interface::interpret-markup + layout props text))) + +(define-public (parentheses-item::calc-angled-bracket-stencils grob) + (let* ( + (font (ly:grob-default-font grob)) + (lp (ly:stencil-aligned-to (ly:stencil-aligned-to (grob-text grob (ly:wide-char->utf-8 #x2329)) + Y CENTER) X RIGHT)) + (rp (ly:stencil-aligned-to (ly:stencil-aligned-to (grob-text grob (ly:wide-char->utf-8 #x232A)) + Y CENTER) X LEFT)) + ) + + (list (stencil-whiteout lp) + (stencil-whiteout rp)))) + (define (parenthesize-elements grob . rest) (let* ((refp (if (null? rest) @@ -292,10 +343,9 @@ centered, X==1 is at the right, X == -1 is at the left." (car rest))) (elts (ly:grob-object grob 'elements)) (x-ext (ly:relative-group-extent elts refp X)) - - (font (ly:grob-default-font grob)) - (lp (ly:font-get-glyph font "accidentals.leftparen")) - (rp (ly:font-get-glyph font "accidentals.rightparen")) + (stencils (ly:grob-property grob 'stencils)) + (lp (car stencils)) + (rp (cadr stencils)) (padding (ly:grob-property grob 'padding 0.1))) (ly:stencil-add @@ -324,6 +374,7 @@ centered, X==1 is at the right, X == -1 is at the left." )) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; diff --git a/scm/stencil.scm b/scm/stencil.scm index b2d425e6ea..62b43cebc2 100644 --- a/scm/stencil.scm +++ b/scm/stencil.scm @@ -118,13 +118,32 @@ encloses the contents. `(text ,font-metric ,text) (car b) (cdr b)))) (define-public (fontify-text-white scale font-metric text) - "Set TEXT with scale factor s" + "Set TEXT with scale factor SCALE" (let* ((b (ly:text-dimension font-metric text)) ;;urg -- workaround for using ps font (c `(white-text ,(* 2 scale) ,text))) ;;urg -- extent is not from ps font, but we hope it's close (ly:make-stencil c (car b) (cdr b)))) +(define-public (stencil-with-color stencil color) + (ly:make-stencil + (list 'color color (ly:stencil-expr stencil)) + (ly:stencil-extent stencil X) + (ly:stencil-extent stencil Y))) + +(define-public (stencil-whiteout stencil) + (let* + ((x-ext (ly:stencil-extent stencil X)) + (y-ext (ly:stencil-extent stencil Y)) + + ) + + (ly:stencil-add + (stencil-with-color (ly:round-filled-box x-ext y-ext 0.0) + white) + stencil) + )) + (define-public (dimension-arrows destination) "Draw twosided arrow from here to @var{destination}" -- 2.39.5