X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fengraver-group.cc;h=cf1832fe1fb73dd25f93e621e7a20d077485bbd0;hb=ec91a9a4bdd186d7af88381a10a2923ac949d33c;hp=f876bf2605f5928fa60a220e866d1c45b644109d;hpb=90d3ec050c58d6fa91f668dd6ca1ae8f16df20c3;p=lilypond.git diff --git a/lily/engraver-group.cc b/lily/engraver-group.cc index f876bf2605..cf1832fe1f 100644 --- a/lily/engraver-group.cc +++ b/lily/engraver-group.cc @@ -1,311 +1,241 @@ /* - engravergroup.cc -- implement Engraver_group_engraver + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter + Copyright (C) 1997--2015 Han-Wen Nienhuys - (c) 1997 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 + 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 "proto.hh" -#include "plist.hh" +#include "context.hh" +#include "dispatcher.hh" #include "engraver-group.hh" -#include "engraver.hh" -#include "debug.hh" -#include "p-score.hh" -#include "score-elem.hh" -#include "input-translator.hh" -Engraver* get_engraver_p(String); - -Engraver_group_engraver::~Engraver_group_engraver() -{ - assert(removable_b()); -} +#include "global-context.hh" +#include "grob.hh" +#include "grob-properties.hh" +#include "paper-score.hh" +#include "translator-dispatch-list.hh" +#include "warn.hh" void -Engraver_group_engraver::check_removal() -{ - for (int i =0; i < group_l_arr_.size(); ) { - group_l_arr_[i]->check_removal(); - if (group_l_arr_[i]->removable_b()) - terminate_engraver(group_l_arr_[i]); - else - i++; +Engraver_group::override (SCM sev) +{ + Stream_event *ev = unsmob (sev); + SCM sym = ev->get_property ("symbol"); + Grob_property_info gpi (context (), sym); + + if (to_boolean (ev->get_property ("once"))) + { + SCM token = gpi.temporary_override (ev->get_property ("property-path"), + ev->get_property ("value")); + if (scm_is_pair (token)) + if (Global_context *g = context ()->get_global_context ()) + { + g->add_finalization (scm_list_4 (ly_context_matched_pop_property_proc, + context ()->self_scm (), + sym, + token)); + } } - -} - -bool -Engraver_group_engraver::removable_b()const -{ - return !iterator_count_&& !group_l_arr_.size() ; -} - -Engraver_group_engraver::Engraver_group_engraver() -{ - itrans_l_ =0; + else + gpi.push (ev->get_property ("property-path"), + ev->get_property ("value")); } void -Engraver_group_engraver::set_feature(Feature d) -{ - iter_top(grav_list_, i); - while (i.ok()) { - // this construction to ensure clean deletion - Engraver *grav_l = i++; - grav_l->set_feature(d); +Engraver_group::revert (SCM sev) +{ + Stream_event *ev = unsmob (sev); + SCM sym = ev->get_property ("symbol"); + Grob_property_info gpi (context (), sym); + + if (to_boolean (ev->get_property ("once"))) + { + SCM token = gpi.temporary_revert (ev->get_property ("property-path")); + if (scm_is_pair (token)) + if (Global_context *g = context ()->get_global_context ()) + { + g->add_finalization (scm_list_4 (ly_context_matched_pop_property_proc, + context ()->self_scm (), + sym, + token)); + } } + else + gpi.pop (ev->get_property ("property-path")); } void -Engraver_group_engraver::sync_features() +Engraver_group::connect_to_context (Context *c) { - iter_top(grav_list_, i); - while (i.ok()) { - - Engraver *grav_l = i++; - grav_l->sync_features(); - } + Translator_group::connect_to_context (c); + c->event_source ()->add_listener (GET_LISTENER (Engraver_group, override), ly_symbol2scm ("Override")); + c->event_source ()->add_listener (GET_LISTENER (Engraver_group, revert), ly_symbol2scm ("Revert")); } void -Engraver_group_engraver::do_pre_move_processing() +Engraver_group::disconnect_from_context () { - iter_top(grav_list_, i); - while (i.ok()) { - - Engraver *grav_l = i++; - grav_l->pre_move_processing(); - } + context ()->event_source ()->remove_listener (GET_LISTENER (Engraver_group, override), ly_symbol2scm ("Override")); + context ()->event_source ()->remove_listener (GET_LISTENER (Engraver_group, revert), ly_symbol2scm ("Revert")); + Translator_group::disconnect_from_context (); } void -Engraver_group_engraver::do_process_requests() +Engraver_group::announce_grob (Grob_info info) { - iter_top(grav_list_, i); - while (i.ok()) { - - Engraver *grav_l = i++; - grav_l->process_requests(); - } -} + announce_infos_.push_back (info); - -void -Engraver_group_engraver::do_post_move_processing() -{ - iter_top(grav_list_, i); - while (i.ok()) { - // this construction to ensure clean deletion - Engraver *grav_l = i++; - grav_l->post_move_processing(); + Context *dad_con = context_->get_parent_context (); + if (info.rerouting_daddy_context_) + { + dad_con = info.rerouting_daddy_context_; + info.rerouting_daddy_context_ = 0; } -} + Engraver_group *dad_eng + = dad_con + ? dynamic_cast (dad_con->implementation ()) + : 0; -bool -Engraver_group_engraver::contains_b(Engraver* grav_l)const -{ - bool parent_b = Engraver::contains_b(grav_l); - - if (parent_b) - return true; - for (iter_top(grav_list_, j); j.ok(); j++) - if (j->contains_b(grav_l)) - return true; - return false; -} - - - -bool -Engraver_group_engraver::do_try_request(Request*req_l) -{ - bool hebbes_b =false; - for (int i =0; !hebbes_b && i < nongroup_l_arr_.size() ; i++) - hebbes_b =nongroup_l_arr_[i]->try_request(req_l); - if (!hebbes_b) - hebbes_b = daddy_grav_l_->try_request(req_l); - return hebbes_b ; -} - -bool -Engraver_group_engraver::try_request(Request* r) -{ - return Engraver::try_request(r); + if (dad_eng) + dad_eng->announce_grob (info); } void -Engraver_group_engraver::add(Engraver *grav_p) +Engraver_group::acknowledge_grobs () { - grav_list_.bottom().add(grav_p); - grav_p->daddy_grav_l_ = this; + if (!announce_infos_.size ()) + return; - if (grav_p->is_type_b(Engraver_group_engraver::static_name())) { - group_l_arr_.push((Engraver_group_engraver*)grav_p); - } else { - nongroup_l_arr_ .push(grav_p); - } -} + SCM name_sym = ly_symbol2scm ("name"); + for (vsize j = 0; j < announce_infos_.size (); j++) + { + Grob_info info = announce_infos_[j]; -Engraver * -Engraver_group_engraver::remove_engraver_p(Engraver*grav_l) -{ - group_l_arr_.substitute((Engraver_group_engraver*)grav_l,0); - nongroup_l_arr_.substitute(grav_l,0); - iterator(grav_list_) grav_cur= grav_list_.find(grav_l); - - return grav_cur.remove_p(); -} + SCM meta = info.grob ()->get_property ("meta"); + SCM nm = scm_assoc (name_sym, meta); + if (scm_is_pair (nm)) + nm = scm_cdr (nm); + else + continue; -void -Engraver_group_engraver::terminate_engraver(Engraver*r_l) -{ - mtor << "Removing " << r_l->name() << " at " << get_staff_info().when() << "\n"; - r_l->do_removal_processing(); - Engraver * grav_p =remove_engraver_p(r_l); - - delete grav_p; -} + SCM ackhandle = scm_hashq_create_handle_x (acknowledge_hash_table_drul_[info.start_end ()], + nm, SCM_BOOL_F); -IMPLEMENT_IS_TYPE_B2(Engraver_group_engraver,Engraver, Translator); -IMPLEMENT_STATIC_NAME(Engraver_group_engraver); -ADD_THIS_ENGRAVER(Engraver_group_engraver); + SCM acklist = scm_cdr (ackhandle); -void -Engraver_group_engraver::do_print()const -{ -#ifndef NPRINT - mtor << "ID: " << id_str_ << "\n"; - for (iter_top(grav_list_, i); i.ok(); i++) - i->print(); -#endif -} + if (scm_is_false (acklist)) + { + SCM ifaces + = scm_cdr (scm_assoc (ly_symbol2scm ("interfaces"), meta)); + acklist = Engraver_dispatch_list::create (get_simple_trans_list (), + ifaces, info.start_end ()); + scm_set_cdr_x (ackhandle, acklist); + } -Engraver_group_engraver* -Engraver_group_engraver::find_engraver_l(String n, String id) -{ - if (name() == n && id_str_ == id) - return this; - Engraver_group_engraver * r = 0; - for (int i =0; !r && i< group_l_arr_.size(); i++) { - r = group_l_arr_[i]->find_engraver_l(n,id); - } - - return r; -} + Engraver_dispatch_list *dispatch + = unsmob (acklist); -Translator* -Engraver_group_engraver::find_get_translator_l(String n,String id) -{ - Translator * ret=0; - Input_translator * itrans_l= itrans_l_-> recursive_find ( n ); - if (itrans_l ) { - ret = find_engraver_l(n,id); - if (!ret) { - Engraver_group_engraver * group = - itrans_l-> get_group_engraver_p(); - - add(group); - ret = group; - - if (group->itrans_l_->is_name_b( n ) ) - ret ->id_str_ = id; - else - return ret->find_get_translator_l(n,id); - - } - } else if (daddy_grav_l_) - ret =daddy_grav_l_->find_get_translator_l(n,id); - else { - warning("Can't find or create `" + n + "' called `" + id + "'\n"); - ret =0; + if (dispatch) + dispatch->apply (info); } - return ret; } -int -Engraver_group_engraver::depth_i()const -{ - return daddy_grav_l_->depth_i() + 1; -} - -Translator* -Engraver_group_engraver::ancestor_l(int l) -{ - if (!l || !daddy_grav_l_) - return this; - - return daddy_grav_l_->ancestor_l(l-1); +/* + Ugh. This is slightly expensive. We could/should cache the value of + the group count? +*/ +bool +Engraver_group::pending_grobs () const +{ + if (!announce_infos_.empty ()) + return true; + for (SCM s = context_->children_contexts (); + scm_is_pair (s); s = scm_cdr (s)) + { + Context *c = unsmob (scm_car (s)); + Engraver_group *group + = dynamic_cast (c->implementation ()); + + if (group && group->pending_grobs ()) + return true; + } + return false; } void -Engraver_group_engraver::announce_element(Score_elem_info info) -{ - announce_info_arr_.push(info); - Engraver::announce_element(info); +Engraver_group::do_announces () +{ + do + { + /* + DOCME: why is this inside the loop? + */ + for (SCM s = context ()->children_contexts (); + scm_is_pair (s); s = scm_cdr (s)) + { + Context *c = unsmob (scm_car (s)); + Engraver_group *group + = dynamic_cast (c->implementation ()); + if (group) + group->do_announces (); + } + + while (1) + { + precomputed_translator_foreach (PROCESS_ACKNOWLEDGED); + if (announce_infos_.size () == 0) + break; + + acknowledge_grobs (); + announce_infos_.clear (); + } + } + while (pending_grobs ()); } -void -Engraver_group_engraver::do_announces() +Engraver_group::Engraver_group () { - for (int i=0; i < group_l_arr_.size(); i++) { - group_l_arr_[i]->do_announces(); - } - - Request dummy_req; - - for (int j =0; j < announce_info_arr_.size(); j++){ - Score_elem_info info = announce_info_arr_[j]; - - if (!info.req_l_) - info.req_l_ = &dummy_req; - for (int i=0; i < nongroup_l_arr_.size(); i++) { // Is this good enough?6 - if (nongroup_l_arr_[i] != info.origin_grav_l_arr_[0]) - nongroup_l_arr_[i]->acknowledge_element(info); - } - } - announce_info_arr_.set_size(0); + acknowledge_hash_table_drul_[LEFT] + = acknowledge_hash_table_drul_[RIGHT] + = SCM_EOL; + + acknowledge_hash_table_drul_[LEFT] = scm_c_make_hash_table (61); + acknowledge_hash_table_drul_[RIGHT] = scm_c_make_hash_table (61); } +#include "translator.icc" -void -Engraver_group_engraver::do_removal_processing() -{ - for (iter( grav_list_.top(), i); i.ok(); i++) - i->do_removal_processing(); -} +ADD_TRANSLATOR_GROUP (Engraver_group, + /* doc */ + "A group of engravers taken together.", -Staff_info -Engraver_group_engraver::get_staff_info()const -{ - Staff_info inf = Engraver::get_staff_info(); + /* create */ + "", - for (int i=0; i < nongroup_l_arr_.size(); i++) - nongroup_l_arr_[i]->fill_staff_info(inf); - - return inf; -} + /* read */ + "", -Translator* -Engraver_group_engraver::get_default_interpreter() -{ - // ? - if ( is_bottom_engraver_b() ) - return daddy_grav_l_->get_default_interpreter(); - - Engraver_group_engraver *grav_p= itrans_l_-> - get_default_itrans_l()->get_group_engraver_p(); - add(grav_p ); - if (grav_p->is_bottom_engraver_b()) - return grav_p; - else - return grav_p->get_default_interpreter(); -} + /* write */ + "" + ); -bool -Engraver_group_engraver::is_bottom_engraver_b()const +void +Engraver_group::derived_mark () const { - return !itrans_l_->get_default_itrans_l(); + scm_gc_mark (acknowledge_hash_table_drul_[LEFT]); + scm_gc_mark (acknowledge_hash_table_drul_[RIGHT]); }