X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fpage-turn-engraver.cc;h=b294dce7d7f803ca9b083d4a75235870178d2b01;hb=a6a51abfd0195a3cf7d6ea095cf69808852f21ce;hp=522ae7559eb46e029d539549607f274534a7d7ff;hpb=87eedcd59f4082cb0841528ad5bc82cb1d1191e3;p=lilypond.git diff --git a/lily/page-turn-engraver.cc b/lily/page-turn-engraver.cc index 522ae7559e..b294dce7d7 100644 --- a/lily/page-turn-engraver.cc +++ b/lily/page-turn-engraver.cc @@ -1,9 +1,20 @@ /* - page-turn-engraver.cc -- implement Page_turn_engraver + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter + Copyright (C) 2006--2015 Joe Neeman - (c) 2006--2007 Joe Neeman + 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 "engraver.hh" @@ -18,7 +29,8 @@ #include "translator.icc" -class Page_turn_event { +class Page_turn_event +{ public: SCM permission_; Real penalty_; @@ -45,8 +57,8 @@ public: if (intersect.is_empty ()) { - ret.push_back (*this); - return ret; + ret.push_back (*this); + return ret; } Real new_pen = max (penalty_, penalty.penalty_); @@ -54,7 +66,7 @@ public: if (duration_[LEFT] < penalty.duration_[LEFT]) ret.push_back (Page_turn_event (duration_[LEFT], penalty.duration_[LEFT], permission_, penalty_)); - if (penalty.permission_ != SCM_EOL) + if (!scm_is_null (penalty.permission_)) ret.push_back (Page_turn_event (intersect[LEFT], intersect[RIGHT], permission_, new_pen)); if (penalty.duration_[RIGHT] < duration_[RIGHT]) @@ -77,7 +89,7 @@ class Page_turn_engraver : public Engraver /* the next 3 are in sync (ie. same number of elements, etc.) */ vector breakable_moments_; - vector breakable_columns_; + vector breakable_columns_; vector special_barlines_; SCM max_permission (SCM perm1, SCM perm2); @@ -85,8 +97,8 @@ class Page_turn_engraver : public Engraver Grob *breakable_column (Page_turn_event const &); protected: - DECLARE_TRANSLATOR_LISTENER (break); - DECLARE_ACKNOWLEDGER (note_head); + void listen_break (Stream_event *); + void acknowledge_note_head (Grob_info); public: TRANSLATOR_DECLARATIONS (Page_turn_engraver); @@ -95,7 +107,8 @@ public: void finalize (); }; -Page_turn_engraver::Page_turn_engraver () +Page_turn_engraver::Page_turn_engraver (Context *c) + : Engraver (c) { repeat_begin_ = Moment (-1); repeat_begin_rest_length_ = 0; @@ -103,7 +116,7 @@ Page_turn_engraver::Page_turn_engraver () note_end_ = 0; } -Grob* +Grob * Page_turn_engraver::breakable_column (Page_turn_event const &brk) { vsize start = lower_bound (breakable_moments_, brk.duration_[LEFT], less ()); @@ -136,9 +149,9 @@ Page_turn_engraver::acknowledge_note_head (Grob_info gi) Stream_event *cause = gi.event_cause (); Duration *dur_ptr = cause - ? unsmob_duration (cause->get_property ("duration")) - : 0; - + ? unsmob (cause->get_property ("duration")) + : 0; + if (!dur_ptr) return; @@ -146,9 +159,9 @@ Page_turn_engraver::acknowledge_note_head (Grob_info gi) { Real pen = penalty ((now_mom () - rest_begin_).main_part_); if (!isinf (pen)) - automatic_breaks_.push_back (Page_turn_event (rest_begin_.main_part_, - now_mom ().main_part_, - ly_symbol2scm ("allow"), 0)); + automatic_breaks_.push_back (Page_turn_event (rest_begin_.main_part_, + now_mom ().main_part_, + ly_symbol2scm ("allow"), 0)); } if (rest_begin_ <= repeat_begin_) @@ -156,11 +169,10 @@ Page_turn_engraver::acknowledge_note_head (Grob_info gi) note_end_ = now_mom () + dur_ptr->get_length (); } -IMPLEMENT_TRANSLATOR_LISTENER (Page_turn_engraver, break); void Page_turn_engraver::listen_break (Stream_event *ev) { - string name = ly_scm2string (scm_symbol_to_string (ev->get_property ("class"))); + string name = ly_symbol2string (scm_car (ev->get_property ("class"))); if (name == "page-turn-event") { @@ -196,7 +208,7 @@ Page_turn_engraver::start_translation_timestep () void Page_turn_engraver::stop_translation_timestep () { - Grob *pc = unsmob_grob (get_property ("currentCommandColumn")); + Grob *pc = unsmob (get_property ("currentCommandColumn")); if (pc) { @@ -217,24 +229,24 @@ Page_turn_engraver::stop_translation_timestep () for (; scm_is_pair (cs); cs = scm_cdr (cs)) { SCM command = scm_car (cs); - if (command == ly_symbol2scm ("start-repeat")) - start = true; - else if (command == ly_symbol2scm ("end-repeat")) - end = true; + if (scm_is_eq (command, ly_symbol2scm ("start-repeat"))) + start = true; + else if (scm_is_eq (command, ly_symbol2scm ("end-repeat"))) + end = true; } if (end && repeat_begin_.main_part_ >= Moment (0)) { Rational now = now_mom ().main_part_; Real pen = penalty ((now_mom () - rest_begin_).main_part_ + repeat_begin_rest_length_); - Moment *m = unsmob_moment (get_property ("minimumRepeatLengthForPageTurn")); + Moment *m = unsmob (get_property ("minimumRepeatLengthForPageTurn")); if (m && *m > (now_mom () - repeat_begin_)) - pen = infinity_f; + pen = infinity_f; if (pen == infinity_f) - repeat_penalties_.push_back (Page_turn_event (repeat_begin_.main_part_, now, SCM_EOL, -infinity_f)); + repeat_penalties_.push_back (Page_turn_event (repeat_begin_.main_part_, now, SCM_EOL, -infinity_f)); else - repeat_penalties_.push_back (Page_turn_event (repeat_begin_.main_part_, now, ly_symbol2scm ("allow"), pen)); + repeat_penalties_.push_back (Page_turn_event (repeat_begin_.main_part_, now, ly_symbol2scm ("allow"), pen)); repeat_begin_ = Moment (-1); } @@ -253,9 +265,10 @@ Page_turn_engraver::stop_translation_timestep () SCM Page_turn_engraver::max_permission (SCM perm1, SCM perm2) { - if (perm1 == SCM_EOL) + if (scm_is_null (perm1)) return perm2; - if (perm1 == ly_symbol2scm ("allow") && perm2 == ly_symbol2scm ("force")) + if (scm_is_eq (perm1, ly_symbol2scm ("allow")) + && scm_is_eq (perm2, ly_symbol2scm ("force"))) return perm2; return perm1; } @@ -273,30 +286,30 @@ Page_turn_engraver::finalize () /* find the next applicable repeat penalty */ for (; - rep_index < repeat_penalties_.size () - && repeat_penalties_[rep_index].duration_[RIGHT] <= brk.duration_[LEFT]; - rep_index++) - ; + rep_index < repeat_penalties_.size () + && repeat_penalties_[rep_index].duration_[RIGHT] <= brk.duration_[LEFT]; + rep_index++) + ; if (rep_index >= repeat_penalties_.size () - || brk.duration_[RIGHT] <= repeat_penalties_[rep_index].duration_[LEFT]) - auto_breaks.push_back (brk); + || brk.duration_[RIGHT] <= repeat_penalties_[rep_index].duration_[LEFT]) + auto_breaks.push_back (brk); else - { - vector split = brk.penalize (repeat_penalties_[rep_index]); - - /* it's possible that the last of my newly-split events overlaps the next repeat_penalty, - in which case we need to refilter that event */ - if (rep_index + 1 < repeat_penalties_.size () - && split.size () - && split.back ().duration_[RIGHT] > repeat_penalties_[rep_index+1].duration_[LEFT]) - { - automatic_breaks_[i] = split.back (); - split.pop_back (); - i--; - } - auto_breaks.insert (auto_breaks.end (), split.begin (), split.end ()); - } + { + vector split = brk.penalize (repeat_penalties_[rep_index]); + + /* it's possible that the last of my newly-split events overlaps the next repeat_penalty, + in which case we need to refilter that event */ + if (rep_index + 1 < repeat_penalties_.size () + && split.size () + && split.back ().duration_[RIGHT] > repeat_penalties_[rep_index + 1].duration_[LEFT]) + { + automatic_breaks_[i] = split.back (); + split.pop_back (); + i--; + } + auto_breaks.insert (auto_breaks.end (), split.begin (), split.end ()); + } } /* apply the automatic breaks */ @@ -305,34 +318,49 @@ Page_turn_engraver::finalize () Page_turn_event const &brk = auto_breaks[i]; Grob *pc = breakable_column (auto_breaks[i]); if (pc) - { - SCM perm = max_permission (pc->get_property ("page-turn-permission"), brk.permission_); - Real pen = min (robust_scm2double (pc->get_property ("page-turn-penalty"), infinity_f), brk.penalty_); - pc->set_property ("page-turn-permission", perm); - pc->set_property ("page-turn-penalty", scm_from_double (pen)); - } + { + SCM perm = max_permission (pc->get_property ("page-turn-permission"), brk.permission_); + Real pen = min (robust_scm2double (pc->get_property ("page-turn-penalty"), infinity_f), brk.penalty_); + pc->set_property ("page-turn-permission", perm); + pc->set_property ("page-turn-penalty", scm_from_double (pen)); + } } + /* unless a manual break overrides it, allow a page turn at the end of the piece */ + breakable_columns_.back ()->set_property ("page-turn-permission", ly_symbol2scm ("allow")); + /* apply the manual breaks */ for (vsize i = 0; i < forced_breaks_.size (); i++) { Page_turn_event const &brk = forced_breaks_[i]; Grob *pc = breakable_column (forced_breaks_[i]); if (pc) - { - pc->set_property ("page-turn-permission", brk.permission_); - pc->set_property ("page-turn-penalty", scm_from_double (brk.penalty_)); - } + { + pc->set_property ("page-turn-permission", brk.permission_); + pc->set_property ("page-turn-penalty", scm_from_double (brk.penalty_)); + } } } -ADD_ACKNOWLEDGER (Page_turn_engraver, note_head); + +void +Page_turn_engraver::boot () +{ + ADD_LISTENER (Page_turn_engraver, break); + ADD_ACKNOWLEDGER (Page_turn_engraver, note_head); +} ADD_TRANSLATOR (Page_turn_engraver, - /* doc */ "Decide where page turns are allowed to go", - /* create */ "", + /* doc */ + "Decide where page turns are allowed to go.", + + /* create */ + "", + /* read */ - "minimumPageTurnLength " - "minimumRepeatLengthForPageTurn ", - /* write */ "" - ); + "minimumPageTurnLength " + "minimumRepeatLengthForPageTurn ", + + /* write */ + "" + );