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 "paper-def.hh"
13 #include "paper-outputter.hh"
14 #include "paper-line.hh"
18 int Page::page_count_ = 0;
19 Real Page::MIN_COVERAGE_ = 0.66;
21 Page::Page (Paper_def *paper, int number)
37 hsize_ = paper->get_dimension (ly_symbol2scm ("hsize"));
38 vsize_ = paper->get_dimension (ly_symbol2scm ("vsize"));
39 top_margin_ = paper->get_dimension (ly_symbol2scm ("top-margin"));
40 bottom_margin_ = paper->get_dimension (ly_symbol2scm ("bottom-margin"));
41 head_sep_ = paper->get_dimension (ly_symbol2scm ("head-sep"));
42 foot_sep_ = paper->get_dimension (ly_symbol2scm ("foot-sep"));
43 text_width_ = paper->get_dimension (ly_symbol2scm ("linewidth"));
44 left_margin_ = (hsize_ - text_width_) / 2;
46 SCM make_header = ly_scheme_function ("make-header");
47 SCM make_footer = ly_scheme_function ("make-footer");
49 header_ = scm_call_2 (make_header, paper_->self_scm (),
50 scm_int2num (number_));
51 if (unsmob_stencil (header_))
52 unsmob_stencil (header_)->align_to (Y_AXIS, UP);
54 footer_ = scm_call_2 (make_footer, paper_->self_scm (),
55 scm_int2num (number_));
56 if (unsmob_stencil (footer_))
57 unsmob_stencil (footer_)->align_to (Y_AXIS, UP);
66 #include "ly-smobs.icc"
68 IMPLEMENT_DEFAULT_EQUAL_P (Page)
69 IMPLEMENT_SMOBS (Page)
70 IMPLEMENT_TYPE_P (Page, "ly:page?")
73 Page::mark_smob (SCM smob)
75 Page *p = (Page*) SCM_CELL_WORD_1 (smob);
76 scm_gc_mark (p->lines_);
77 scm_gc_mark (p->header_);
78 scm_gc_mark (p->footer_);
79 scm_gc_mark (p->copyright_);
80 scm_gc_mark (p->tagline_);
85 Page::print_smob (SCM smob, SCM port, scm_print_state*)
87 Page *p = (Page*) ly_cdr (smob);
88 scm_puts ("#<", port);
89 scm_puts (classname (p), port);
90 scm_puts (to_string (p->number_).to_str0 (), port);
97 stack_stencils (Stencil &a, Stencil *b, Offset *origin)
99 Real height = b->extent (Y_AXIS).length ();
102 programming_error (to_string ("Improbable stencil height: %f", height));
109 (*origin)[Y_AXIS] += height;
113 Page::to_stencil () const
115 SCM proc = ly_scheme_function ("page-to-stencil");
116 return scm_call_1 (proc, self_scm ());
119 LY_DEFINE (ly_page_header_lines_footer_stencil, "ly:page-header-lines-footer-stencil",
121 "Simple header, lines, footer stencil from PAGE.")
123 Page *p = unsmob_page (page);
124 SCM_ASSERT_TYPE (p, page, SCM_ARG1, __FUNCTION__, "page");
127 Offset o (p->left_margin_, p->top_margin_);
128 Real vfill = (p->line_count_ > 1
129 ? (p->text_height () - p->height_) / (p->line_count_ - 1)
132 Real coverage = p->height_ / p->text_height ();
133 if (coverage < p->MIN_COVERAGE_)
134 /* Do not space out a badly filled page. This is too simplistic
135 (ie broken), because this should not vary too much between
136 (subsequent?) pages in a book. */
139 if (Stencil *s = unsmob_stencil (p->header_))
141 stack_stencils (stencil, s, &o);
142 o[Y_AXIS] += p->head_sep_;
144 for (SCM s = p->lines_; s != SCM_EOL; s = ly_cdr (s))
146 Paper_line *p = unsmob_paper_line (ly_car (s));
147 #if 0 // ugh, parse error?
148 Stencil line (Box (Interval (0, p->dim ()[X_AXIS]),
149 Interval (0, p->dim ()[Y_AXIS])), SCM_EOL);
151 Box x (Interval (0, p->dim ()[X_AXIS]),
152 Interval (0, p->dim ()[Y_AXIS]));
153 Stencil line (x, SCM_EOL);
155 line.add_stencil (*unsmob_stencil (p->to_stencil ()));
156 stack_stencils (stencil, &line, &o);
158 /* Do not put vfill between title and its music, */
159 if (ly_cdr (s) != SCM_EOL
160 && (!p->is_title () || vfill < 0))
162 /* rather put extra just before the title. */
163 if (ly_cdr (s) != SCM_EOL
164 && (unsmob_paper_line (ly_cadr (s))->is_title () && vfill > 0))
168 o[Y_AXIS] = p->vsize_ - p->bottom_margin_;
169 if (unsmob_stencil (p->copyright_))
170 o[Y_AXIS] -= unsmob_stencil (p->copyright_)->extent (Y_AXIS).length ();
171 if (unsmob_stencil (p->tagline_))
172 o[Y_AXIS] -= unsmob_stencil (p->tagline_)->extent (Y_AXIS).length ();
173 if (unsmob_stencil (p->footer_))
174 o[Y_AXIS] -= unsmob_stencil (p->footer_)->extent (Y_AXIS).length ();
176 if (Stencil *s = unsmob_stencil (p->copyright_))
177 stack_stencils (stencil, s, &o);
178 if (Stencil *s = unsmob_stencil (p->tagline_))
179 stack_stencils (stencil, s, &o);
180 if (Stencil *s = unsmob_stencil (p->footer_))
181 stack_stencils (stencil, s, &o);
183 return stencil.smobbed_copy ();
187 Page::text_height () const
189 Real h = vsize_ - top_margin_ - bottom_margin_;
190 if (unsmob_stencil (header_))
191 h -= unsmob_stencil (header_)->extent (Y_AXIS).length () + head_sep_;
192 if (unsmob_stencil (copyright_) || unsmob_stencil (tagline_) || unsmob_stencil (footer_))
194 if (unsmob_stencil (copyright_))
195 h -= unsmob_stencil (copyright_)->extent (Y_AXIS).length ();
196 if (unsmob_stencil (tagline_))
197 h -= unsmob_stencil (tagline_)->extent (Y_AXIS).length ();
198 if (unsmob_stencil (footer_))
199 h -= unsmob_stencil (footer_)->extent (Y_AXIS).length ();