+/* return the most permissive symbol (where force is the most permissive and
+ forbid is the least
+*/
+SCM
+Page_turn_engraver::max_permission (SCM perm1, SCM perm2)
+{
+ if (perm1 == SCM_EOL)
+ return perm2;
+ if (perm1 == ly_symbol2scm ("allow") && perm2 == ly_symbol2scm ("force"))
+ return perm2;
+ return perm1;
+}
+
+void
+Page_turn_engraver::finalize ()
+{
+ vsize rep_index = 0;
+ vector<Page_turn_event> auto_breaks;
+
+ /* filter the automatic breaks through the repeat penalties */
+ for (vsize i = 0; i < automatic_breaks_.size (); i++)
+ {
+ Page_turn_event &brk = automatic_breaks_[i];
+
+ /* find the next applicable repeat penalty */
+ for (;
+ 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);
+ else
+ {
+ vector<Page_turn_event> 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 */
+ for (vsize i = 0; i < auto_breaks.size (); i++)
+ {
+ 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));
+ }
+ }
+
+ /* 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_));
+ }
+ }
+}