From b17364183c12506d30bfc19bcbf650c4441b7949 Mon Sep 17 00:00:00 2001 From: Paul Morris Date: Sat, 23 Jan 2016 21:38:16 -0500 Subject: [PATCH] Issue 4743/1: Add ly:one-line-auto-height-breaking --- lily/include/one-line-auto-height-breaking.hh | 35 ++++++ lily/one-line-auto-height-breaking.cc | 103 ++++++++++++++++++ lily/one-line-page-breaking.cc | 7 +- lily/page-breaking-scheme.cc | 16 ++- 4 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 lily/include/one-line-auto-height-breaking.hh create mode 100644 lily/one-line-auto-height-breaking.cc diff --git a/lily/include/one-line-auto-height-breaking.hh b/lily/include/one-line-auto-height-breaking.hh new file mode 100644 index 0000000000..92209de04e --- /dev/null +++ b/lily/include/one-line-auto-height-breaking.hh @@ -0,0 +1,35 @@ +/* + This file is part of LilyPond, the GNU music typesetter. + + Copyright (C) 2012 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 . +*/ + +#ifndef ONE_LINE_AUTO_HEIGHT_BREAKING_HH +#define ONE_LINE_AUTO_HEIGHT_BREAKING_HH + +#include "page-breaking.hh" +#include "page-spacing.hh" + +class One_line_auto_height_breaking: public Page_breaking +{ +public: + virtual SCM solve (); + + One_line_auto_height_breaking (Paper_book *pb); + virtual ~One_line_auto_height_breaking (); +}; + +#endif /* ONE_LINE_AUTO_HEIGHT_BREAKING_HH */ diff --git a/lily/one-line-auto-height-breaking.cc b/lily/one-line-auto-height-breaking.cc new file mode 100644 index 0000000000..bb0698fed4 --- /dev/null +++ b/lily/one-line-auto-height-breaking.cc @@ -0,0 +1,103 @@ +/* + This file is part of LilyPond, the GNU music typesetter. + + Copyright (C) 2012 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 "one-line-auto-height-breaking.hh" + +#include + +#include "column-x-positions.hh" +#include "international.hh" +#include "output-def.hh" +#include "page-spacing.hh" +#include "paper-book.hh" +#include "paper-score.hh" +#include "simple-spacer.hh" +#include "system.hh" + +One_line_auto_height_breaking::One_line_auto_height_breaking (Paper_book *pb) + : Page_breaking (pb, 0, 0) +{ +} + +One_line_auto_height_breaking::~One_line_auto_height_breaking () +{ +} + +/* + This is a somewhat unconventional page-breaking algorithm. Like + ly:one-line-breaking, every score is put on a single page, whose width + is enough to fit the entire score on one line. Line breaks and page + breaks are ignored, and the paper-width setting in the paper + block is modified to fit the music. Unlike ly:one-line-breaking + the paper-height setting in the paper block is also modified to fit + the music. +*/ +SCM +One_line_auto_height_breaking::solve () +{ + SCM all_pages = SCM_EOL; + Real max_width = 0; + Real max_height = 0; + + for (vsize i = 0; i < system_specs_.size (); ++i) + { + if (Paper_score *ps = system_specs_[i].pscore_) + { + vector cols = ps->root_system ()->used_columns (); + + // No indent, "infinite" line width, ragged. + Column_x_positions pos = get_line_configuration (cols, numeric_limits::max (), 0, true); + vector positions; + positions.push_back (pos); + + ps->root_system ()->break_into_pieces (positions); + ps->root_system ()->do_break_substitution_and_fixup_refpoints (); + Grob *system = ps->root_system ()->broken_intos_[0]; + + vector lines_per_page; + lines_per_page.push_back (1); + SCM systems = scm_list_1 (system->self_scm ()); + SCM pages = make_pages (lines_per_page, systems); + + max_width = max (max_width, system->extent (system, X_AXIS).length ()); + max_height = max (max_height, system->extent (system, Y_AXIS).length ()); + all_pages = scm_cons (scm_car (pages), all_pages); + } + else if (Prob *pb = system_specs_[i].prob_) + // Because we don't call Page_breaking::systems in this algorithm, + // we need to manually unprotect the titles. + pb->unprotect (); + } + + // Alter paper-width so that it is large enough to fit every system. + // TODO: it might be nice to allow different pages to have different widths + // and heights. This would need support in the backends (eg. framework-ps.scm). + Real right_margin = robust_scm2double (book_->paper_->c_variable ("right-margin"), 0.0); + Real left_margin = robust_scm2double (book_->paper_->c_variable ("left-margin"), 0.0); + Real width = max_width + right_margin + left_margin; + book_->paper_->set_variable (ly_symbol2scm ("paper-width"), scm_from_double (width)); + + // Alter paper-height so that it fits the height of the tallest system. + Real top_margin = robust_scm2double (book_->paper_->c_variable ("top-margin"), 0.0); + Real bottom_margin = robust_scm2double (book_->paper_->c_variable ("bottom-margin"), 0.0); + Real height = max_height + top_margin + bottom_margin; + book_->paper_->set_variable (ly_symbol2scm ("paper-height"), scm_from_double (height)); + + return scm_reverse_x (all_pages, SCM_EOL); +} diff --git a/lily/one-line-page-breaking.cc b/lily/one-line-page-breaking.cc index 213864462f..a3276f4216 100644 --- a/lily/one-line-page-breaking.cc +++ b/lily/one-line-page-breaking.cc @@ -41,10 +41,9 @@ One_line_page_breaking::~One_line_page_breaking () /* This is a somewhat unconventional page-breaking algorithm. Every - score will be put on a single page, whose width is enough - to fit the entire score one one line. Line breaks and page breaks - are ignored, and the paper-width setting in the paper block - will be modified to fit the music. + score is put on a single page, whose width is enough to fit the entire + score on one line. Line breaks and page breaks are ignored, and the + paper-width setting in the paper block is modified to fit the music. */ SCM One_line_page_breaking::solve () diff --git a/lily/page-breaking-scheme.cc b/lily/page-breaking-scheme.cc index 70ec63971d..0c806493b4 100644 --- a/lily/page-breaking-scheme.cc +++ b/lily/page-breaking-scheme.cc @@ -20,6 +20,7 @@ #include "paper-book.hh" #include "page-turn-page-breaking.hh" #include "one-line-page-breaking.hh" +#include "one-line-auto-height-breaking.hh" #include "optimal-page-breaking.hh" #include "minimal-page-breaking.hh" @@ -56,9 +57,20 @@ LY_DEFINE (ly_minimal_breaking, "ly:minimal-breaking", LY_DEFINE (ly_one_line_breaking, "ly:one-line-breaking", 1, 0, 0, (SCM pb), "Put each score on a single line, and put each line on its own" - " page. The paper-width setting will be modified so that" - " every page will be wider than the widest line.") + " page. Modify the paper-width setting so that every page" + " is wider than the widest line.") { One_line_page_breaking b (unsmob (pb)); return b.solve (); } + +LY_DEFINE (ly_one_line_auto_height_breaking, "ly:one-line-auto-height-breaking", + 1, 0, 0, (SCM pb), + "Put each score on a single line, and put each line on its own" + " page. Modify the paper-width setting so that every page" + " is wider than the widest line. Modify the paper-height" + " setting to fit the height of the tallest line.") +{ + One_line_auto_height_breaking b (unsmob (pb)); + return b.solve (); +} -- 2.39.5