X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fnew-dynamic-engraver.cc;h=cd7db644a66f409ebdc46f3ee151a76f870fc010;hb=740139c0fc7c61a5864b304fef73c736c342ed96;hp=497fc0b7f710c145c1b44310e4d9c86618282118;hpb=a6bd229f7fe1dc4a03478e14ccc0c0c66b225061;p=lilypond.git diff --git a/lily/new-dynamic-engraver.cc b/lily/new-dynamic-engraver.cc index 497fc0b7f7..cd7db644a6 100644 --- a/lily/new-dynamic-engraver.cc +++ b/lily/new-dynamic-engraver.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 2008--2010 Han-Wen Nienhuys + Copyright (C) 2008--2012 Han-Wen Nienhuys LilyPond is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,6 +36,7 @@ class New_dynamic_engraver : public Engraver DECLARE_ACKNOWLEDGER (note_column); DECLARE_TRANSLATOR_LISTENER (absolute_dynamic); DECLARE_TRANSLATOR_LISTENER (span_dynamic); + DECLARE_TRANSLATOR_LISTENER (break_span); protected: virtual void process_music (); @@ -44,7 +45,7 @@ protected: private: SCM get_property_setting (Stream_event *evt, char const *evprop, - char const *ctxprop); + char const *ctxprop); string get_spanner_type (Stream_event *ev); Drul_array accepted_spanevents_drul_; @@ -54,6 +55,7 @@ private: Item *script_; Stream_event *script_event_; Stream_event *current_span_event_; + bool end_new_spanner_; }; New_dynamic_engraver::New_dynamic_engraver () @@ -64,6 +66,7 @@ New_dynamic_engraver::New_dynamic_engraver () finished_spanner_ = 0; current_spanner_ = 0; accepted_spanevents_drul_.set (0, 0); + end_new_spanner_ = false; } IMPLEMENT_TRANSLATOR_LISTENER (New_dynamic_engraver, absolute_dynamic); @@ -82,10 +85,26 @@ New_dynamic_engraver::listen_span_dynamic (Stream_event *ev) ASSIGN_EVENT_ONCE (accepted_spanevents_drul_[d], ev); } +IMPLEMENT_TRANSLATOR_LISTENER (New_dynamic_engraver, break_span); +void +New_dynamic_engraver::listen_break_span (Stream_event *event) +{ + if (event->in_event_class ("break-dynamic-span-event")) + { + // Case 1: Already have a start dynamic event -> break applies to new + // spanner (created later) -> set a flag + // Case 2: no new spanner, but spanner already active -> break it now + if (accepted_spanevents_drul_[START]) + end_new_spanner_ = true; + else if (current_spanner_) + current_spanner_->set_property ("spanner-broken", SCM_BOOL_T); + } +} + SCM New_dynamic_engraver::get_property_setting (Stream_event *evt, - char const *evprop, - char const *ctxprop) + char const *evprop, + char const *ctxprop) { SCM spanner_type = evt->get_property (evprop); if (spanner_type == SCM_EOL) @@ -98,15 +117,15 @@ New_dynamic_engraver::process_music () { if (current_spanner_ && (accepted_spanevents_drul_[STOP] - || script_event_ - || accepted_spanevents_drul_[START])) + || script_event_ + || accepted_spanevents_drul_[START])) { Stream_event *ender = accepted_spanevents_drul_[STOP]; if (!ender) - ender = script_event_; + ender = script_event_; if (!ender) - ender = accepted_spanevents_drul_[START]; + ender = accepted_spanevents_drul_[START]; finished_spanner_ = current_spanner_; announce_end_grob (finished_spanner_, ender->self_scm ()); @@ -120,53 +139,66 @@ New_dynamic_engraver::process_music () string start_type = get_spanner_type (current_span_event_); SCM cresc_type = get_property_setting (current_span_event_, "span-type", - (start_type + "Spanner").c_str ()); + (start_type + "Spanner").c_str ()); if (cresc_type == ly_symbol2scm ("text")) - { - current_spanner_ - = make_spanner ("DynamicTextSpanner", - accepted_spanevents_drul_[START]->self_scm ()); - - SCM text = get_property_setting (current_span_event_, "span-text", - (start_type + "Text").c_str ()); - if (Text_interface::is_markup (text)) - current_spanner_->set_property ("text", text); - } + { + current_spanner_ + = make_spanner ("DynamicTextSpanner", + accepted_spanevents_drul_[START]->self_scm ()); + + SCM text = get_property_setting (current_span_event_, "span-text", + (start_type + "Text").c_str ()); + if (Text_interface::is_markup (text)) + current_spanner_->set_property ("text", text); + /* + If the line of a text spanner is hidden, end the alignment spanner + early: this allows dynamics to be spaced individually instead of + being linked together. + */ + if (current_spanner_->get_property ("style") == ly_symbol2scm ("none")) + current_spanner_->set_property ("spanner-broken", SCM_BOOL_T); + } else - { - if (cresc_type != ly_symbol2scm ("hairpin")) - { - string as_string = ly_scm_write_string (cresc_type); - current_span_event_ - ->origin()->warning (_f ("unknown crescendo style: %s\ndefaulting to hairpin.", as_string.c_str())); - } - current_spanner_ = make_spanner ("Hairpin", - current_span_event_->self_scm ()); - } + { + if (cresc_type != ly_symbol2scm ("hairpin")) + { + string as_string = ly_scm_write_string (cresc_type); + current_span_event_ + ->origin ()->warning (_f ("unknown crescendo style: %s\ndefaulting to hairpin.", as_string.c_str ())); + } + current_spanner_ = make_spanner ("Hairpin", + current_span_event_->self_scm ()); + } + // if we have a break-dynamic-span event right after the start dynamic, break the new spanner immediately + if (end_new_spanner_) + { + current_spanner_->set_property ("spanner-broken", SCM_BOOL_T); + end_new_spanner_ = false; + } if (finished_spanner_) - { - if (Hairpin::has_interface (finished_spanner_)) - Pointer_group_interface::add_grob (finished_spanner_, - ly_symbol2scm ("adjacent-spanners"), - current_spanner_); - if (Hairpin::has_interface (current_spanner_)) - Pointer_group_interface::add_grob (current_spanner_, - ly_symbol2scm ("adjacent-spanners"), - finished_spanner_); - } + { + if (Hairpin::has_interface (finished_spanner_)) + Pointer_group_interface::add_grob (finished_spanner_, + ly_symbol2scm ("adjacent-spanners"), + current_spanner_); + if (Hairpin::has_interface (current_spanner_)) + Pointer_group_interface::add_grob (current_spanner_, + ly_symbol2scm ("adjacent-spanners"), + finished_spanner_); + } } if (script_event_) { script_ = make_item ("DynamicText", script_event_->self_scm ()); script_->set_property ("text", - script_event_->get_property ("text")); + script_event_->get_property ("text")); if (finished_spanner_) - finished_spanner_->set_bound (RIGHT, script_); + finished_spanner_->set_bound (RIGHT, script_); if (current_spanner_) - current_spanner_->set_bound (LEFT, script_); + current_spanner_->set_bound (LEFT, script_); } } @@ -175,17 +207,18 @@ New_dynamic_engraver::stop_translation_timestep () { if (finished_spanner_ && !finished_spanner_->get_bound (RIGHT)) finished_spanner_ - ->set_bound (RIGHT, - unsmob_grob (get_property ("currentMusicalColumn"))); + ->set_bound (RIGHT, + unsmob_grob (get_property ("currentMusicalColumn"))); if (current_spanner_ && !current_spanner_->get_bound (LEFT)) current_spanner_ - ->set_bound (LEFT, - unsmob_grob (get_property ("currentMusicalColumn"))); + ->set_bound (LEFT, + unsmob_grob (get_property ("currentMusicalColumn"))); script_ = 0; script_event_ = 0; accepted_spanevents_drul_.set (0, 0); finished_spanner_ = 0; + end_new_spanner_ = false; } void @@ -197,9 +230,9 @@ New_dynamic_engraver::finalize () if (current_spanner_) { current_span_event_ - ->origin ()->warning (_f ("unterminated %s", - get_spanner_type (current_span_event_) - .c_str ())); + ->origin ()->warning (_f ("unterminated %s", + get_spanner_type (current_span_event_) + .c_str ())); current_spanner_->suicide (); current_spanner_ = 0; } @@ -209,7 +242,7 @@ string New_dynamic_engraver::get_spanner_type (Stream_event *ev) { string type; - SCM start_sym = ev->get_property ("class"); + SCM start_sym = scm_car (ev->get_property ("class")); if (start_sym == ly_symbol2scm ("decrescendo-event")) type = "decrescendo"; @@ -227,12 +260,21 @@ New_dynamic_engraver::acknowledge_note_column (Grob_info info) if (script_ && !script_->get_parent (X_AXIS)) { extract_grob_set (info.grob (), "note-heads", heads); - if (heads.size ()) - { - Grob *head = heads[0]; - script_->set_parent (head, X_AXIS); - Self_alignment_interface::set_center_parent (script_, X_AXIS); - } + Grob *stem = unsmob_grob (info.grob ()->get_object ("stem")); + /* + Spacing constraints may require dynamics to be aligned on rests, + so check for a rest if this note column has no note heads. + */ + Grob *x_parent = (heads.size () + ? heads[0] + : unsmob_grob (info.grob ()->get_object ("rest"))); + if (x_parent) + { + script_->set_parent (x_parent, X_AXIS); + Self_alignment_interface::set_center_parent (script_, X_AXIS); + } + if (stem) + Pointer_group_interface::add_grob (script_, ly_symbol2scm ("potential-X-colliding-grobs"), stem); } if (current_spanner_ && !current_spanner_->get_bound (LEFT)) @@ -243,24 +285,21 @@ New_dynamic_engraver::acknowledge_note_column (Grob_info info) ADD_ACKNOWLEDGER (New_dynamic_engraver, note_column); ADD_TRANSLATOR (New_dynamic_engraver, - /* doc */ - "Create hairpins, dynamic texts, and their vertical" - " alignments. The symbols are collected onto a" - " @code{DynamicLineSpanner} grob which takes care of vertical" - " positioning.", - - /* create */ - "DynamicTextSpanner " - "DynamicText " - "Hairpin ", - - /* read */ - "crescendoSpanner " - "crescendoText " - "currentMusicalColumn " - "decrescendoSpanner " - "decrescendoText ", - - /* write */ - "" - ); + /* doc */ + "Create hairpins, dynamic texts and dynamic text spanners.", + + /* create */ + "DynamicTextSpanner " + "DynamicText " + "Hairpin ", + + /* read */ + "crescendoSpanner " + "crescendoText " + "currentMusicalColumn " + "decrescendoSpanner " + "decrescendoText ", + + /* write */ + "" + );