From 75e31df11f879be81a489a4dd9cba837d4d6bebf Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Sat, 5 Oct 2002 01:46:24 +0000 Subject: [PATCH] * lily/horizontal-bracket.cc: new file. * lily/horizontal-bracket-engraver.cc: new file. * input/regression/note-group-bracket.ly: new file. Support horizontal note brackets for music analysis. * lily/stem.cc (flag): new flag-style: no-flag. * input/test/stem-cross-staff.ly: new file --- ChangeLog | 11 +++ Documentation/user/refman.itely | 27 +++++- VERSION | 2 +- input/regression/note-group-bracket.ly | 30 ++++++ input/test/stem-cross-staff.ly | 35 +++++++ lily/accidental.cc | 2 +- lily/ambitus.cc | 4 +- lily/custos.cc | 2 +- lily/grob-interface.cc | 2 +- lily/horizontal-bracket-engraver.cc | 126 +++++++++++++++++++++++++ lily/horizontal-bracket.cc | 70 ++++++++++++++ lily/key-signature-interface.cc | 2 +- lily/lily-guile.cc | 4 - lily/porrectus.cc | 2 +- lily/staff-symbol.cc | 1 - lily/stem.cc | 16 ++-- ly/spanners-init.ly | 19 +++- scm/grob-description.scm | 9 ++ scm/grob-property-description.scm | 5 +- scm/lily.scm | 16 ++-- scm/music-types.scm | 6 ++ 21 files changed, 356 insertions(+), 35 deletions(-) create mode 100644 input/regression/note-group-bracket.ly create mode 100644 input/test/stem-cross-staff.ly create mode 100644 lily/horizontal-bracket-engraver.cc create mode 100644 lily/horizontal-bracket.cc diff --git a/ChangeLog b/ChangeLog index f8268e65eb..dd19eebb81 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 2002-10-05 Han-Wen Nienhuys + * lily/horizontal-bracket.cc: new file. + + * lily/horizontal-bracket-engraver.cc: new file. + + * input/regression/note-group-bracket.ly: new file. Support + horizontal note brackets for music analysis. + + * lily/stem.cc (flag): new flag-style: no-flag. + + * input/test/stem-cross-staff.ly: new file + * lily/include/midi-stream.hh: use stdio.h iso. iostream.h * lily/parser.yy: remove \dynamicscript. diff --git a/Documentation/user/refman.itely b/Documentation/user/refman.itely index d85545b73f..9868e18287 100644 --- a/Documentation/user/refman.itely +++ b/Documentation/user/refman.itely @@ -2842,9 +2842,32 @@ c''4 \sostenutoDown d''4 e''4 c'4 f'4 g'4 a'4 \sostenutoUp @end lilypond +@node Cross staff stems +@subsection Cross staff stems +@cindex Cross staff stems +@cindex Stems, cross staff +Unfortunately, there is no support for putting chords across staves. +You can get this result by increasing the length of the stem in the +lower stave so it reaches the stem in the upper stave, or vice versa. + +@lilypond + +sUp = \translator Staff = "up" +sDown = \translator Staff = "down" + +stemExtend = \property Voice.Stem \set #'length = #22 +stemNormal = \property Voice.Slur \revert #'length + + + < { \stemDown \sDown s4. a, } \\ + { \stemDown \sUp f4. \stemExtend f }> | + + \stemNormal + + [...] +@end lilypond -@c . {Arpeggio} @node Arpeggio @subsection Arpeggio @cindex Arpeggio @@ -4955,8 +4978,6 @@ instruments and ranges or change the default settings by overriding the Both loudness controls are combined to produce the final MIDI volume. - - @menu * MIDI block:: * MIDI instrument names:: diff --git a/VERSION b/VERSION index 27ff91f4a7..6acfe3a8d0 100644 --- a/VERSION +++ b/VERSION @@ -1,7 +1,7 @@ PACKAGE_NAME=LilyPond MAJOR_VERSION=1 MINOR_VERSION=7 -PATCH_LEVEL=1 +PATCH_LEVEL=2 MY_PATCH_LEVEL= # Use the above to send patches: MY_PATCH_LEVEL is always empty for a diff --git a/input/regression/note-group-bracket.ly b/input/regression/note-group-bracket.ly new file mode 100644 index 0000000000..abae7ca1df --- /dev/null +++ b/input/regression/note-group-bracket.ly @@ -0,0 +1,30 @@ + +\header { + + texidoc = "Note grouping events are used to indicate where +brackets for analysis start and end." + +} + + + +\score { + \notes + { + + c4-\groupOpen-\groupOpen-\groupOpen + c4-\groupClose + c4-\groupOpen + c4-\groupClose-\groupClose + c4-\groupOpen + c4-\groupClose-\groupClose + } + + \paper { + \translator { + \StaffContext \consists "Horizontal_bracket_engraver" + } + + linewidth = -1.0 + } +} diff --git a/input/test/stem-cross-staff.ly b/input/test/stem-cross-staff.ly new file mode 100644 index 0000000000..be99ca0c5f --- /dev/null +++ b/input/test/stem-cross-staff.ly @@ -0,0 +1,35 @@ +\header { + texidoc = "Cross staff stems + +Unfortunately, there is no support for putting chords across staves. +You can get this result by increasing the length of the stem in the +lower stave so it reaches the stem in the upper stave, or vice versa. + +@cindex Cross staff stems +@cindex Stems, cross staff + +" +} + +stemExtend = \once \property Voice.Stem \override #'length = #22 + +%% following reqs 1.7.1 or better. +noFlag = \once \property Voice.Stem \override #'flag-style = #'no-flag + + +\score { \notes + \context PianoStaff + < \context Staff = up { + \stemDown + \stemExtend + f'4 + \stemExtend + \noFlag + f'8 } + \context Staff = down { + \clef bass + a4 a8 } + > + + \paper { linewidth = -1.0 } +} diff --git a/lily/accidental.cc b/lily/accidental.cc index 426f94fbb6..11f0a0184c 100644 --- a/lily/accidental.cc +++ b/lily/accidental.cc @@ -166,7 +166,7 @@ Accidental_interface::brew_molecule (SCM smob) String style; if (gh_symbol_p (scm_style)) { - style = ly_scm2string (scm_symbol_to_string (scm_style)); + style = ly_symbol2string (scm_style); } else { diff --git a/lily/ambitus.cc b/lily/ambitus.cc index a7ee2c9a46..35c7fcc30d 100644 --- a/lily/ambitus.cc +++ b/lily/ambitus.cc @@ -133,7 +133,7 @@ Ambitus::brew_molecule (SCM smob) if (gh_symbol_p (scm_note_head_style)) { String note_head_style = - ly_scm2string (scm_symbol_to_string (scm_note_head_style)); + ly_symbol2string (scm_note_head_style); } else { @@ -225,7 +225,7 @@ Ambitus::brew_molecule (SCM smob) if (gh_symbol_p (scm_accidentals_style)) { accidentals_style = - ly_scm2string (scm_symbol_to_string (scm_accidentals_style)); + ly_symbol2string (scm_accidentals_style); } else { diff --git a/lily/custos.cc b/lily/custos.cc index 4def4d6f22..3b6d91cc38 100644 --- a/lily/custos.cc +++ b/lily/custos.cc @@ -36,7 +36,7 @@ Custos::brew_molecule (SCM smob) String style; if (gh_symbol_p (scm_style)) { - style = ly_scm2string (scm_symbol_to_string (scm_style)); + style = ly_symbol2string (scm_style); } else { diff --git a/lily/grob-interface.cc b/lily/grob-interface.cc index 8d0d394c02..55ebe58299 100644 --- a/lily/grob-interface.cc +++ b/lily/grob-interface.cc @@ -67,7 +67,7 @@ check_interfaces_for_property (Grob const *me, SCM sym) if (iface == SCM_BOOL_F) { String msg = to_string ("Unknown interface `%s'", - ly_scm2string (scm_symbol_to_string (gh_car(ifs))).to_str0 ()); + ly_symbol2string (gh_car(ifs)).to_str0 ()); programming_error (msg); continue; } diff --git a/lily/horizontal-bracket-engraver.cc b/lily/horizontal-bracket-engraver.cc new file mode 100644 index 0000000000..f4c819aa29 --- /dev/null +++ b/lily/horizontal-bracket-engraver.cc @@ -0,0 +1,126 @@ +/* + horizontal-bracket-engraver.cc -- implement + Horizontal_bracket_engraver + +source file of the GNU LilyPond music typesetter + +(c) 2002 Han-Wen Nienhuys + + */ + +#include "engraver.hh" +#include "side-position-interface.hh" +#include "note-column.hh" +#include "group-interface.hh" + +class Horizontal_bracket_engraver : public Engraver +{ +public: + TRANSLATOR_DECLARATIONS(Horizontal_bracket_engraver); + Link_array bracket_stack_; + Link_array events_; + int pop_count_; + int push_count_; + + virtual bool try_music(Music*); + virtual void start_translation_timestep (); + virtual void stop_translation_timestep (); + virtual void process_music (); + virtual void acknowledge_grob (Grob_info); +}; + +ENTER_DESCRIPTION(Horizontal_bracket_engraver, + "Create horizontal brackets over notes for musical analysis purposes.", + "HorizontalBracket", + "note-grouping-event", + "note-column-interface", + "", + ""); + +Horizontal_bracket_engraver::Horizontal_bracket_engraver() +{ + pop_count_ = 0; + push_count_ = 0; +} + +void +Horizontal_bracket_engraver::start_translation_timestep() +{ + pop_count_ = 0; + push_count_ = 0; +} + +bool +Horizontal_bracket_engraver::try_music (Music *m) +{ + if (m->is_mus_type ("note-grouping-event")) + { + Direction d = to_dir (m->get_mus_property ("span-direction")); + + if (d == STOP) + { + pop_count_ ++; + if (pop_count_ > bracket_stack_.size()) + m->origin()->warning (_("Don't have that many brackets.")); + } + else + { + push_count_++; + events_.push (m); + } + + if (pop_count_ && push_count_) + m->origin()->warning (_("Conflicting note group events.")); + + return true; + } + return false; +} + +void +Horizontal_bracket_engraver::acknowledge_grob (Grob_info gi) +{ + if (Note_column::has_interface (gi.grob_)) + { + for (int i = 0; i < bracket_stack_.size(); i++) + { + Side_position_interface::add_support (bracket_stack_[i], gi.grob_); + Pointer_group_interface::add_grob (bracket_stack_[i], + ly_symbol2scm ("columns"), gi.grob_); + add_bound_item (bracket_stack_[i], + gi.grob_); + } + } +} + +void +Horizontal_bracket_engraver::process_music () +{ + for (int k = 0; k < push_count_; k++) + { + Spanner * sp = new Spanner (get_property ("HorizontalBracket")); + + announce_grob (sp, events_[k]->self_scm()); + for (int i = 0; i < bracket_stack_.size(); i++) + { + /* + sp is the smallest, it should be added to the bigger brackets. + */ + Side_position_interface::add_support (bracket_stack_[i], sp); + } + bracket_stack_.push (sp); + } +} + + +void +Horizontal_bracket_engraver::stop_translation_timestep () +{ + for (int i = pop_count_; i--;) + { + if (bracket_stack_.size()) + typeset_grob (bracket_stack_.pop()); + } +} + + diff --git a/lily/horizontal-bracket.cc b/lily/horizontal-bracket.cc new file mode 100644 index 0000000000..6ecdec1e58 --- /dev/null +++ b/lily/horizontal-bracket.cc @@ -0,0 +1,70 @@ +/* +horizontal-bracket.cc -- implement + +source file of the GNU LilyPond music typesetter + +(c) 2002 Han-Wen Nienhuys + + */ + +#include "side-position-interface.hh" +#include "lookup.hh" +#include "group-interface.hh" +#include "directional-element-interface.hh" +#include "paper-def.hh" + +struct Horizontal_bracket +{ + DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM)); + static bool has_interface (Grob*); +}; + + +/* + TODO: + + This doesn't look very elegant: should support winged edges. + + Support texts on the brackets? + +*/ + +MAKE_SCHEME_CALLBACK(Horizontal_bracket, brew_molecule, 1); + +SCM +Horizontal_bracket::brew_molecule (SCM smob) +{ + Grob * me = unsmob_grob (smob); + Spanner *sp = dynamic_cast (me); + Link_array gs = Pointer_group_interface__extract_grobs (me,(Grob*)0, "columns"); + + if (!gs.size()) + { + me->suicide(); + return SCM_EOL; + } + Grob * cx = common_refpoint_of_array (gs, me, X_AXIS); + cx = cx->common_refpoint (sp->get_bound (LEFT), X_AXIS); + cx = cx->common_refpoint (sp->get_bound (RIGHT),X_AXIS); + + Interval ext = gs.top()->extent (cx, X_AXIS); + ext.unite (gs[0]->extent (cx, X_AXIS)); + + Direction d = Directional_element_interface::get (me); + Real t = me->get_paper()->get_var ("linethickness"); + + SCM lthick = me->get_grob_property ("thickness"); + if (gh_number_p (lthick)) + t *= gh_scm2double (lthick); + + Molecule b = Lookup::bracket (X_AXIS, ext, t, - d* 1.0); + + b.translate_axis ( - sp->get_bound (LEFT)->relative_coordinate (cx, X_AXIS), X_AXIS); + + return b.smobbed_copy(); +} + +ADD_INTERFACE (Horizontal_bracket,"horizontal-bracket-interface", + "A horizontal bracket encompassing notes.", + "thickness columns direction"); + diff --git a/lily/key-signature-interface.cc b/lily/key-signature-interface.cc index 81946e2769..76bf41d2b0 100644 --- a/lily/key-signature-interface.cc +++ b/lily/key-signature-interface.cc @@ -104,7 +104,7 @@ Key_signature_interface::brew_molecule (SCM smob) String style; if (gh_symbol_p (scm_style)) { - style = ly_scm2string (scm_symbol_to_string (scm_style)); + style = ly_symbol2string (scm_style); } else { diff --git a/lily/lily-guile.cc b/lily/lily-guile.cc index 357800bbdb..ef50c52027 100644 --- a/lily/lily-guile.cc +++ b/lily/lily-guile.cc @@ -70,8 +70,6 @@ ly_quote_scm (SCM s) return scm_list_n (ly_symbol2scm ("quote"), s, SCM_UNDEFINED); } - - String ly_symbol2string (SCM s) { @@ -79,7 +77,6 @@ ly_symbol2string (SCM s) return String ((Byte*)SCM_STRING_CHARS (s), (int) SCM_STRING_LENGTH (s)); } - String gulp_file_to_string (String fn) { @@ -94,7 +91,6 @@ gulp_file_to_string (String fn) else if (verbose_global_b) progress_indication ("[" + s); - int n; char * str = gulp_file (s, &n); String result (str); diff --git a/lily/porrectus.cc b/lily/porrectus.cc index 8b05d26b76..0dc1468e9a 100644 --- a/lily/porrectus.cc +++ b/lily/porrectus.cc @@ -101,7 +101,7 @@ Porrectus::brew_molecule (SCM smob) SCM scm_style = me->get_grob_property ("style"); String style; if ((gh_symbol_p (scm_style)) && (scm_style != SCM_EOL)) - style = ly_scm2string (scm_symbol_to_string (scm_style)); + style = ly_symbol2string (scm_style); else { me->warning (_ ("porrectus style undefined; using mensural")); style = "mensural"; diff --git a/lily/staff-symbol.cc b/lily/staff-symbol.cc index f669bc57f2..834b9845e9 100644 --- a/lily/staff-symbol.cc +++ b/lily/staff-symbol.cc @@ -37,7 +37,6 @@ Staff_symbol::brew_molecule (SCM smob) --hwn. */ - SCM width_scm = me->get_grob_property ("width"); if (gh_number_p (width_scm)) { diff --git a/lily/stem.cc b/lily/stem.cc index 80bc16bbb7..69cbcb4e6f 100644 --- a/lily/stem.cc +++ b/lily/stem.cc @@ -532,19 +532,23 @@ Stem::flag (Grob*me) /* TODO: maybe property stroke-style should take different values, e.g. "" (i.e. no stroke), "single" and "double" (currently, it's '() or "grace"). */ - String flag_style, staffline_offs; + String flag_style; + SCM flag_style_scm = me->get_grob_property ("flag-style"); if (gh_symbol_p (flag_style_scm)) { - flag_style = ly_scm2string (scm_symbol_to_string (flag_style_scm)); + flag_style = ly_symbol2string (flag_style_scm); } - else + + if (flag_style == "no-flag") { - flag_style = ""; + return Molecule (); } + bool adjust = to_boolean (me->get_grob_property ("adjust-if-on-staffline")); + String staffline_offs; if (String::compare (flag_style, "mensural") == 0) /* Mensural notation: For notes on staff lines, use different flags than for notes between staff lines. The idea is that @@ -592,6 +596,7 @@ Stem::flag (Grob*me) { staffline_offs = ""; } + char dir = (get_direction (me) == UP) ? 'u' : 'd'; String font_char = flag_style + to_string (dir) + staffline_offs + to_string (duration_log (me)); @@ -664,9 +669,6 @@ Stem::brew_molecule (SCM smob) /* TODO: make the stem start a direction ? */ - - - if (to_boolean (me->get_grob_property ("avoid-note-head"))) { Grob * lh = last_head (me); diff --git a/ly/spanners-init.ly b/ly/spanners-init.ly index 1e2a8a819e..bfccd05cab 100644 --- a/ly/spanners-init.ly +++ b/ly/spanners-init.ly @@ -1,9 +1,20 @@ \version "1.5.68" -cr = \spanrequest \start "crescendo" -decr = \spanrequest \start "decrescendo" -rc = \spanrequest \stop "crescendo" -rced = \spanrequest \stop "decrescendo" + +#(define (make-span-request type spandir) + (let* ((m (make-music-by-name type))) + (ly-set-mus-property! m 'span-direction spandir) + m + )) + +groupOpen = #(make-span-request 'NoteGroupingEvent START) +groupClose = #(make-span-request 'NoteGroupingEvent STOP) + + +cr = #(make-span-request 'CrescendoEvent START) +rc = #(make-span-request 'CrescendoEvent STOP) +decr = #(make-span-request 'DecrescendoEvent START) +rced = #(make-span-request 'DecrescendoEvent STOP) cresc = \notes { \commandspanrequest \start "crescendo" diff --git a/scm/grob-description.scm b/scm/grob-description.scm index 985b8f7ef1..ba10482719 100644 --- a/scm/grob-description.scm +++ b/scm/grob-description.scm @@ -379,6 +379,15 @@ (meta . ((interfaces . (hairpin-interface self-alignment-interface dynamic-interface spanner-interface)))) )) + (HorizontalBracket + . ( + (thickness . 1.0) + (molecule-callback . ,Horizontal_bracket::brew_molecule) + (Y-offset-callbacks . (,Side_position_interface::aligned_side)) + (padding . 0.2) + (direction . -1) + (meta . ((interfaces . (horizontal-bracket-interface spanner-interface)))) + )) (InstrumentName . ( (breakable . #t) diff --git a/scm/grob-property-description.scm b/scm/grob-property-description.scm index c74de1a59d..516f4deda5 100644 --- a/scm/grob-property-description.scm +++ b/scm/grob-property-description.scm @@ -191,7 +191,10 @@ typesetting engine is completely oblivious to it. slur dir) -> attachment to determine the attachment (see above). If procedure returns #t, attachment is used. Otherwise, the next procedure is tried.") -(grob-property-description 'flag-style symbol? "a string determining what style of glyph is typeset.") +(grob-property-description + 'flag-style symbol? + "a string determining what style of glyph is typeset on a Stem. + Additionally, @code{no-flag} switches off the flag.") (grob-property-description 'stroke-style string? "set to \"grace\" to turn stroke through flag on.") (grob-property-description 'flag-width-function procedure? "Procedure that computes the width of a half-beam (a non-connecting beam.).") (grob-property-description 'flexa-width number? "width of a flexa shape in a ligature grob.") diff --git a/scm/lily.scm b/scm/lily.scm index ec68b2aeb3..eace878d5c 100644 --- a/scm/lily.scm +++ b/scm/lily.scm @@ -38,13 +38,15 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define X 0) -(define Y 1) -(define LEFT -1) -(define RIGHT 1) -(define UP 1) -(define DOWN -1) -(define CENTER 0) +(define-public X 0) +(define-public Y 1) +(define-public START -1) +(define-public STOP 1) +(define-public LEFT -1) +(define-public RIGHT 1) +(define-public UP 1) +(define-public DOWN -1) +(define-public CENTER 0) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; lily specific variables. diff --git a/scm/music-types.scm b/scm/music-types.scm index 9c69c6f0f2..f2182207ee 100644 --- a/scm/music-types.scm +++ b/scm/music-types.scm @@ -125,6 +125,12 @@ (iterator-ctor . ,Grace_iterator::constructor) (types . (grace-music music-wrapper-music general-music)) )) + (NoteGroupingEvent + . ( + (description . "Start or stop grouping brackets.") + (internal-class-name . "Event") + (types . (general-music event note-grouping-event)) + )) (HyphenEvent . ( (description . "") -- 2.39.2