2 page.cc -- implement Page
4 source file of the GNU LilyPond music typesetter
6 (c) 2004 Jan Nieuwenhuizen <janneke@gnu.org>
9 #include "dimensions.hh"
10 #include "ly-module.hh"
12 #include "output-def.hh"
13 #include "paper-outputter.hh"
14 #include "paper-line.hh"
19 Real Page::MIN_COVERAGE_ = 0.66;
21 Page::Page (SCM lines, Output_def *paper, int number)
38 header_ = scm_call_2 (paper_->c_variable ("make-header"),
40 scm_int2num (number_));
41 if (unsmob_stencil (header_))
42 unsmob_stencil (header_)->align_to (Y_AXIS, UP);
44 footer_ = scm_call_2 (paper_->c_variable ("make-footer"),
46 scm_int2num (number_));
47 if (unsmob_stencil (footer_))
48 unsmob_stencil (footer_)->align_to (Y_AXIS, UP);
51 for (SCM s = lines; ly_c_pair_p (s); s = ly_cdr (s))
53 height_ += unsmob_paper_line (ly_car (s))->dim()[Y_AXIS];
63 #include "ly-smobs.icc"
65 IMPLEMENT_DEFAULT_EQUAL_P (Page)
66 IMPLEMENT_SMOBS (Page)
67 IMPLEMENT_TYPE_P (Page, "ly:page?")
70 Page::mark_smob (SCM smob)
72 Page *p = (Page*) SCM_CELL_WORD_1 (smob);
73 scm_gc_mark (p->header_);
74 scm_gc_mark (p->footer_);
78 scm_gc_mark (p->paper_->self_scm ());
81 scm_gc_mark (p->copyright_);
82 scm_gc_mark (p->tagline_);
83 //scm_gc_mark (p->lines_);
88 Page::print_smob (SCM smob, SCM port, scm_print_state*)
90 Page *p = (Page*) ly_cdr (smob);
91 scm_puts ("#<", port);
92 scm_puts (classname (p), port);
93 scm_puts (to_string (p->number_).to_str0 (), port);
100 stack_stencils (Stencil a, Stencil b, Offset *origin)
102 Real height = b.extent (Y_AXIS).length ();
105 programming_error (to_string ("Improbable stencil height: %f", height));
112 (*origin)[Y_AXIS] += height;
117 Page::to_stencil () const
119 SCM proc = paper_->lookup_variable (ly_symbol2scm ("page-to-stencil"));
120 return *unsmob_stencil (scm_call_1 (proc, self_scm ()));
125 Page::left_margin () const
127 return (paper_->get_dimension (ly_symbol2scm ("hsize"))
128 - paper_->get_dimension (ly_symbol2scm ("linewidth"))) / 2;
131 LY_DEFINE (ly_page_header_lines_footer_stencil, "ly:page-header-lines-footer-stencil",
133 "Simple header, lines, footer stencil from PAGE.")
135 Page *p = unsmob_page (page);
136 SCM_ASSERT_TYPE (p, page, SCM_ARG1, __FUNCTION__, "page");
139 Offset o (p->left_margin (),
140 p->paper_->get_dimension (ly_symbol2scm ("top-margin")));
142 Real vfill = (p->line_count_ > 1
143 ? (p->text_height () - p->height_) / (p->line_count_ - 1)
146 Real coverage = p->height_ / p->text_height ();
147 if (coverage < p->MIN_COVERAGE_)
148 /* Do not space out a badly filled page. This is too simplistic
149 (ie broken), because this should not vary too much between
150 (subsequent?) pages in a book. */
153 if (Stencil *s = unsmob_stencil (p->header_))
155 stencil = stack_stencils (stencil, *s, &o);
156 o[Y_AXIS] += p->paper_->get_dimension (ly_symbol2scm ("head-sep"));
159 for (SCM s = p->lines_; s != SCM_EOL; s = ly_cdr (s))
161 Paper_line *p = unsmob_paper_line (ly_car (s));
162 stencil = stack_stencils (stencil, p->to_stencil (), &o);
163 /* Do not put vfill between title and its music, */
164 if (ly_cdr (s) != SCM_EOL
165 && (!p->is_title () || vfill < 0))
167 /* rather put extra just before the title. */
168 if (ly_cdr (s) != SCM_EOL
169 && (unsmob_paper_line (ly_cadr (s))->is_title () && vfill > 0))
173 o[Y_AXIS] = p->paper_->get_dimension (ly_symbol2scm ("vsize"))
174 - p->paper_->get_dimension (ly_symbol2scm ("bottom-margin"));
175 if (unsmob_stencil (p->copyright_))
176 o[Y_AXIS] -= unsmob_stencil (p->copyright_)->extent (Y_AXIS).length ();
177 if (unsmob_stencil (p->tagline_))
178 o[Y_AXIS] -= unsmob_stencil (p->tagline_)->extent (Y_AXIS).length ();
179 if (unsmob_stencil (p->footer_))
180 o[Y_AXIS] -= unsmob_stencil (p->footer_)->extent (Y_AXIS).length ();
182 if (Stencil *s = unsmob_stencil (p->copyright_))
183 stencil = stack_stencils (stencil, *s, &o);
184 if (Stencil *s = unsmob_stencil (p->tagline_))
185 stencil = stack_stencils (stencil, *s, &o);
186 if (Stencil *s = unsmob_stencil (p->footer_))
187 stencil = stack_stencils (stencil, *s, &o);
189 return stencil.smobbed_copy ();
193 Page::text_height () const
195 Real h = paper_->get_dimension (ly_symbol2scm ("vsize"))
196 - paper_->get_dimension (ly_symbol2scm ("top-margin"))
197 - paper_->get_dimension (ly_symbol2scm ("bottom-margin"));
198 if (unsmob_stencil (header_))
199 h -= unsmob_stencil (header_)->extent (Y_AXIS).length ()
200 + paper_->get_dimension (ly_symbol2scm ("head-sep"));
201 if (unsmob_stencil (copyright_)
202 || unsmob_stencil (tagline_)
203 || unsmob_stencil (footer_))
204 h -= paper_->get_dimension (ly_symbol2scm ("foot-sep"));
205 if (unsmob_stencil (copyright_))
206 h -= unsmob_stencil (copyright_)->extent (Y_AXIS).length ();
207 if (unsmob_stencil (tagline_))
208 h -= unsmob_stencil (tagline_)->extent (Y_AXIS).length ();
209 if (unsmob_stencil (footer_))
210 h -= unsmob_stencil (footer_)->extent (Y_AXIS).length ();
219 LY_DEFINE (ly_page_paper_lines, "ly:page-paper-lines",
221 "Return paper-lines from @var{page}.")
223 Page *p = unsmob_page (page);
224 SCM_ASSERT_TYPE (p, page, SCM_ARG1, __FUNCTION__, "page");
228 LY_DEFINE (ly_page_stencil, "ly:page-stencil",
230 "Return stencil for @var{page}.")
232 Page *p = unsmob_page (page);
233 SCM_ASSERT_TYPE (p, page, SCM_ARG1, __FUNCTION__, "page");
234 return p->to_stencil ().smobbed_copy ();
238 LY_DEFINE (ly_page_last_p, "ly:page-last?",
240 "Is @var{page} the last one?")
242 Page *p = unsmob_page (page);
243 SCM_ASSERT_TYPE (p, page, SCM_ARG1, __FUNCTION__, "page");
244 return ly_bool2scm (p->is_last_);