- SCM calc_height = scm_c_module_lookup (mod, "calc-printable-height");
- SCM make_page = scm_c_module_lookup (mod, "make-page");
-
- calc_height = scm_variable_ref (calc_height);
- make_page = scm_variable_ref (make_page);
-
- SCM page = scm_apply_0 (make_page, scm_list_n (
- book_->self_scm (),
- ly_symbol2scm ("page-number"), scm_from_int (page_num),
- ly_symbol2scm ("is-last-bookpart"), scm_from_bool (last_part),
- ly_symbol2scm ("is-bookpart-last-page"), scm_from_bool (last),
- SCM_UNDEFINED));
- SCM height = scm_apply_1 (calc_height, page, SCM_EOL);
- return scm_to_double (height) - page_top_space_;
+ SCM make_page_scm = scm_c_module_lookup (mod, "make-page");
+
+ make_page_scm = scm_variable_ref (make_page_scm);
+
+ return scm_apply_0 (make_page_scm,
+ scm_list_n (book_->self_scm (),
+ ly_symbol2scm ("page-number"), scm_from_int (page_num),
+ ly_symbol2scm ("is-last-bookpart"), scm_from_bool (last_part),
+ ly_symbol2scm ("is-bookpart-last-page"), scm_from_bool (last),
+ SCM_UNDEFINED));
+}
+
+// Returns the total height of the paper, including margins and
+// space for the header/footer. This is an upper bound on
+// page_height, and it doesn't depend on the current page.
+Real
+Page_breaking::paper_height () const
+{
+ return paper_height_;
+}
+
+Real
+Page_breaking::page_height (int page_num, bool last) const
+{
+ // The caches allow us to store the page heights for any
+ // non-negative page numbers. We use a negative value in the
+ // cache to signal that that position has not yet been initialized.
+ // This means that we won't cache properly if page_num is negative or
+ // if calc_height returns a negative number. But that's likely to
+ // be rare, so it shouldn't affect performance.
+ vector<Real>& cache = last ? last_page_height_cache_ : page_height_cache_;
+ if (page_num >= 0 && (int) cache.size () > page_num && cache[page_num] >= 0)
+ return cache[page_num];
+ else
+ {
+ SCM mod = scm_c_resolve_module ("scm page");
+ SCM page = make_page (page_num, last);
+ SCM calc_height = scm_c_module_lookup (mod, "calc-printable-height");
+ calc_height = scm_variable_ref (calc_height);
+
+ SCM height_scm = scm_apply_1 (calc_height, page, SCM_EOL);
+ Real height = scm_to_double (height_scm);
+
+ if (page_num >= 0)
+ {
+ if ((int) cache.size () <= page_num)
+ cache.resize (page_num + 1, -1);
+ cache[page_num] = height;
+ }
+ return height;
+ }