Export to GitHub

lilypond - issue #884

pageBreak resets page-count property


Posted on Oct 29, 2009 by Helpful Bear

From Chris Snyder:

"According to LNR 4.1.2, the page-count setting sets "The number of pages to be used for a score." The presence of a \pageBreak command in the score, however, causes the score to be split into multiple chunks, each having page-count number of pages. Effectively, the final page count of the score is page-count*(number of \pageBreak commands present + 1) rather than just page-count."

For instance, the following snippet produces a four-pages PDF though page-count is set to 2:

\version "2.13.6"

\paper { page-count = 2 }

\score { \new Staff { \repeat unfold 50 { c'1 } \pageBreak \repeat unfold 50 { c'1 } } }

Of course, an easy solution would be to change the documentation of page-count.

Comment #1

Posted on Jun 2, 2010 by Happy Bird

http://lists.gnu.org/archive/html/lilypond-user/2010-06/msg00001.html

2.12 produces good and expected result (from docs and heads, i'd say), therefore i can not see any reason why it's not a regression. Honestly .)

Comment #2

Posted on Jun 16, 2010 by Happy Bird

I have changed the workings of page-count so that it interacts better with \pageBreak. Now, page-count is a list of integers whose length is one more than the number of forced page breaks, and each element of the list specifies the number of pages between the corresponding page breaks.

Comment #3

Posted on Jun 16, 2010 by Helpful Horse

Comment deleted

Comment #4

Posted on Jun 16, 2010 by Helpful Horse

Hi Joe,

It seems intuitive to me that page-count be absolute, and that \pageBreak simply indicates where the page must break within those page-count pages. The only conflict would occur when #{\pageBreak} > page-count: in that case, Lilypond could/should warn the user, and run off the last (= page-count) page, but still have [exactly] page-count pages.

In other words, we should stick with what the documentation says: 'the page-count setting sets "The number of pages to be used for a score."'

  1. Is this possible?
  2. Why wouldn't this -- which is completely intuitive behaviour to me -- be desired?

Thanks, Kieren.

Comment #5

Posted on Jun 16, 2010 by Helpful Horse

That being said... If I understand your fix correctly, with 5 \pageBreak-s, I can say

\paper { page-count = #'(1 3 2 2 1 3) }

and the score will contain [exactly] 12 pages. This would be quite useful. What happens if I have no \pageBreak-s, but use the same page-count list?

Comment #6

Posted on Jun 16, 2010 by Swift Bear

Comment deleted

Comment #7

Posted on Jun 16, 2010 by Swift Bear

Thanks, Joe, works like a charm. Is it reasonable to make page-count to automatically repeat the last item of the list as necessary to get the n+1 elements? I.e., specifying #'(3 1 2) and 5 \pageBreaks will automatically expand to #'(3 1 2 2 2)?

While I very much appreciate the possibility to give such a list, it'd still be nice to be able to use both a total (single-integer) page-count and forced breaks. On the other hand, I suspect it's hard (especially w.r.t. computation time) to automatically deduce the best integers in the list, summing up to a given page-count. I assume a penalty calculation is there, since that's already needed for the chunk breaking; but simply trying all possibilies of chunk sizes for total page-count of t and a number of forced breaks of m amounts to (t-1) choose m runs of the page-breaking algorithm... D'you think there's still a chance for it, e.g. using a heuristic of starting with an uniform distribution of the pages to the chunks, or counting measures / graphical elements as an estimate?

[ @Kieren: This seems to be the same idea you just proposed. I'm afraid it looks computationally hardly feasible to my eyes... ] [ EDIT: Uhm, on the other hand... It used to work that way in 2.12.x, didn't it? When is was feasible then, it should be feasible now, too, right? ]

Another idea: how hard is it to allow nil values in the list, corresponding to chunks for which LilyPond is free to choose the optimal number of pages? (nil is also a good candidate for missing entries in the list, by the way.)

Comment #8

Posted on Jun 16, 2010 by Swift Ox

Am Mittwoch, 16. Juni 2010, 14:45:10 schrieb lilypond@googlecode.com:

I have changed the workings of page-count so that it interacts better with \pageBreak. Now, page-count is a list of integers whose length is one more than the number of forced page breaks, and each element of the list specifies the number of pages between the corresponding page breaks.

Is this really necessary? I mean, that's the worst solution (albeit the easiest from a developer's point of view, of course) I can think of (short of leaving the broken behavior). If you have a long score, and you want to force one page break, you don't really want the number of pages before that page break fixed, but you want the overall page count fixed. I don't care whether I have 15 or 16 pages before a page break, as long as the overall count is e.g. 32 (divisible by 4, needed for binding).

Also, it makes tweaking a score a PITA. Imagine you have a score with 24 pages, but some breaks are not ideal. Now you insert a page break, but that alone does not work, you'll have to adjust the 24 to a pair of page numbers. Now you want to adjust another page break, but simply inserting \pageBreak is no longer sufficient. Rather you have to adjust the page-count list once more. And for this, you need to keep track of where you inserted ALL OTHER page breaks, because otherwise the page count will be broken all over...

Cheers, Reinhold

Comment #9

Posted on Jun 16, 2010 by Happy Bird

Wow, I didn't realize this would be so controversial. The reason that it's non-trivial to go back to the old behaviour is that it didn't interact well with min-systems-per-page. The short version is this: in order for min-systems-per-page to interact properly with \pageBreak, we need[1] to deal with every \pageBreak-delimited region separately. Otherwise, you could have something like .... \pageBreak c'1 c'1 \pageBreak .... with min-systems-per-page = 2 and the algorithm wouldn't find a solution because the line breaker would (sensibly) always put the whole notes on the same line and the page breaker would only know that there aren't enough systems for min-systems-per-page to be happy, but it wouldn't see exactly where the extra systems needed to be. So I broke the page-breaking algorithm into one piece for each page break, but then, of course, it isn't possible to support some property that needs to see the whole book at once.

Anyway, perhaps it's possible to go back to the old version, with a different way of supporting min-systems-per-page.

[1] It's possible we don't actually need to, but it was certainly the simplest solution.

Comment #10

Posted on Jun 16, 2010 by Happy Rhino

It seems to me like you're trying to account for someone trying to do something stupid (no offense to anyone...). I think that the best solution would be to tell people that they're being stupid ("Warning: Not enough notes between \pageBreak's to satisfy min-systems-per-page requirement") and leave it at that. If someone really wanted two whole notes split onto two lines, it's perfectly sensible to require them to explicitly say so with a \break command - especially since it would enable appropriate behavior for other, non-stupid use cases.

Why this is a big deal (for me, at least) - since the behavior changed I've been manually specifying all breaks (lines too) because it was the only way I could reliably get the layout I wanted. I'd much prefer being able to say "give me six pages, with explicit breaks here and here."

Comment #11

Posted on Jun 16, 2010 by Helpful Horse

I'd much prefer being able to say "give me six pages, with explicit breaks here and here."

+1

This is the way \pageTurn works [or should, in any case], so why not \pageBreak?

Comment #12

Posted on Jun 17, 2010 by Happy Bird

To be picky, \pageTurn doesn't work like this because the page-turn-breaker doesn't listen to page-count. But anyway, I've reverted to the old version of page-count.

Comment #13

Posted on Jun 17, 2010 by Swift Bear

That should be more intuitive. Does it mean min-systems-per-page is now obsolete? Either way, is it possible to keep the list definitions of page-count without much effort? I think that's a useful feature, too.

Comment #14

Posted on Jun 17, 2010 by Happy Bird

No, min-systems-per-page still works, but it won't be as good at finding solutions if the constraints are very strange (the regression tests still work, though).

It would certainly be possible to keep the list version of page-count, but it isn't completely trivial. If you really think it would be useful, I'd suggest opening another issue as a feature request.

Comment #15

Posted on Jun 17, 2010 by Swift Bear

Okay, thanks.

If the list version is not an absolutely low-hanging fruit, as I assumed after your second-to-last commit, I'd too leave it as a (very) low priority feature request, as soon as this one is closed.

Comment #16

Posted on Jun 18, 2010 by Swift Bear

The list version has one major benefit: it's considerably faster. Which seems to back up my conjecture that deducing the optimal chunk sizes seems hard (cf. comment 7)... Does the current (restored old) page-breaking algorithm do something more clever than a simple brute-force search over all "chunks" between the \pageBreaks?

Comment #17

Posted on Jun 18, 2010 by Happy Bird

No, we don't iterate over all possible configurations. We use a dynamic programming algorithm whose running time is quadratic in the length of the book. In the list version, the algorithm is quadratic in the length of the longest gap between forced page breaks, times linear in the number of forced page breaks.

Comment #18

Posted on Jun 21, 2010 by Happy Bird

(No comment was entered for this change.)

Comment #19

Posted on Dec 27, 2010 by Happy Camel

I believe this was incorrectly marked "fixed"; the fix was to revert a proposed patch, but the original regression remains. The following code is from NR 3.2.3 Reference to page numbers. Under 2.12.3 it produces correct output, but under 2.13.44 (and ironically in the NR example!), the page number for Mark A is incorrectly set to 1.

\version "2.12.3" % Mark A is on page 2 %\version "2.13.44" % Mark A is on page 1

\header { tagline = ##f } \book { \label #'firstScore \score { { c'1 \pageBreak \mark A \label #'markA c'1 } }

\markup { The first score begins on page \page-ref #'firstScore "0" "?" } \markup { Mark A is on page \page-ref #'markA "0" "?" } }

Comment #20

Posted on Dec 27, 2010 by Happy Wombat

I've checked this with the versions of Lily that I have, and the behaviour is incorrect from 13.31 onwards.

Comment #21

Posted on Dec 28, 2010 by Happy Rhino

Why downgrade the priority? if it was Critical before, it's Critical now.

Comment #22

Posted on Dec 29, 2010 by Helpful Kangaroo

I've checked this with the versions of Lily that I have, and the behaviour is incorrect from 13.31 onwards.

The original snippet correctly produces two pages on current master (and still works if you change the number of pages, despite the presence of \pageBreak).

Colin's snippet is completely unrelated to this issue.

Comment #23

Posted on Dec 29, 2010 by Happy Rhino

ok, let's move Colin's example into a new issue number, then mark this one as fixed again (and add back the tag for the version number in which it was fixed).

Comment #24

Posted on Dec 29, 2010 by Happy Camel

Created issue 1465 "\pageBreak breaks \page-ref"

Comment #25

Posted on Dec 29, 2010 by Happy Camel

(No comment was entered for this change.)

Comment #26

Posted on Dec 29, 2010 by Happy Wombat

(No comment was entered for this change.)

Status: Verified

Labels:
Type-Defect Priority-Critical Regression fixed_2_13_25