]> git.donarmstrong.com Git - lilypond.git/blob - lily/page.cc
* lily/parser.yy (book_body): set default bookpaper.
[lilypond.git] / lily / page.cc
1 /*
2   page.cc -- implement Page
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2004 Jan Nieuwenhuizen <janneke@gnu.org>
7 */
8
9 #include "dimensions.hh"
10 #include "ly-module.hh"
11 #include "page.hh"
12 #include "paper-def.hh"
13 #include "paper-outputter.hh"
14 #include "paper-line.hh"
15 #include "stencil.hh"
16 #include "warn.hh"
17 #include "book-paper-def.hh"
18
19 int Page::page_count_ = 0;
20 Real Page::MIN_COVERAGE_ = 0.66;
21
22 Book_paper_def *
23 Page::bookpaper () const
24 {
25   return paper_->bookpaper_;
26 }
27
28 Page::Page (Paper_def *paper, int number)
29 {
30   copyright_ = SCM_EOL;
31   footer_ = SCM_EOL;
32   header_ = SCM_EOL;
33   lines_ = SCM_EOL;
34   tagline_ = SCM_EOL;
35   
36   paper_ = paper;
37   number_ = number;
38
39   height_ = 0;
40   line_count_ = 0;
41   
42   page_count_++;
43
44   header_ = scm_call_2 (paper_->c_variable ("make-header"),
45                         paper_->self_scm (),
46                         scm_int2num (number_));
47   if (unsmob_stencil (header_))
48     unsmob_stencil (header_)->align_to (Y_AXIS, UP);
49     
50   footer_ = scm_call_2 (paper_->c_variable ("make-footer"),
51                         paper_->self_scm (),
52                         scm_int2num (number_));
53   if (unsmob_stencil (footer_))
54     unsmob_stencil (footer_)->align_to (Y_AXIS, UP);
55
56   smobify_self ();
57 }
58
59 Page::~Page ()
60 {
61 }
62
63 #include "ly-smobs.icc"
64
65 IMPLEMENT_DEFAULT_EQUAL_P (Page)
66 IMPLEMENT_SMOBS (Page)
67 IMPLEMENT_TYPE_P (Page, "ly:page?")
68
69 SCM
70 Page::mark_smob (SCM smob)
71 {
72   Page *p = (Page*) SCM_CELL_WORD_1 (smob);
73   scm_gc_mark (p->header_);
74   scm_gc_mark (p->footer_);
75
76   if (p->paper_)
77     {
78       scm_gc_mark (p->paper_->self_scm ());
79       if (p->bookpaper ())
80         {
81           scm_gc_mark (p->bookpaper ()->self_scm ());
82         }
83     }
84   
85   scm_gc_mark (p->copyright_);
86   scm_gc_mark (p->tagline_);
87   //scm_gc_mark (p->lines_);
88   return p->lines_;
89 }
90
91 int
92 Page::print_smob (SCM smob, SCM port, scm_print_state*)
93 {
94   Page *p = (Page*) ly_cdr (smob);
95   scm_puts ("#<", port);
96   scm_puts (classname (p), port);
97   scm_puts (to_string (p->number_).to_str0 (), port);
98   scm_puts (" ", port);
99   scm_puts (">", port);
100   return 1;
101 }
102
103 static Stencil
104 stack_stencils (Stencil a, Stencil b, Offset *origin)
105 {
106   Real height = b.extent (Y_AXIS).length ();
107   if (height > 50 CM)
108     {
109       programming_error (to_string ("Improbable stencil height: %f", height));
110       height = 50 CM;
111     }
112   Offset o = *origin;
113   o.mirror (Y_AXIS);
114   b.translate (o);
115   a.add_stencil (b);
116   (*origin)[Y_AXIS] += height;
117   return a;
118 }
119
120 Stencil
121 Page::to_stencil () const
122 {
123   SCM proc = paper_->lookup_variable (ly_symbol2scm ("page-to-stencil"));
124   return *unsmob_stencil (scm_call_1 (proc, self_scm ()));
125 }
126
127 //urg
128 Real
129 Page::left_margin () const
130 {
131   return (paper_->get_dimension (ly_symbol2scm ("hsize"))
132           - paper_->get_dimension (ly_symbol2scm ("linewidth"))) / 2;
133 }
134
135 LY_DEFINE (ly_page_header_lines_footer_stencil, "ly:page-header-lines-footer-stencil",
136            1, 0, 0, (SCM page),
137            "Simple header, lines, footer stencil from PAGE.")
138 {
139   Page *p = unsmob_page (page);
140   SCM_ASSERT_TYPE (p, page, SCM_ARG1, __FUNCTION__, "page");
141   
142   Stencil stencil;
143   Offset o (p->left_margin (),
144             p->paper_->get_dimension (ly_symbol2scm ("top-margin")));
145
146   Real vfill = (p->line_count_ > 1
147                 ? (p->text_height () - p->height_) / (p->line_count_ - 1)
148                 : 0);
149
150   Real coverage = p->height_ / p->text_height ();
151   if (coverage < p->MIN_COVERAGE_)
152     /* Do not space out a badly filled page.  This is too simplistic
153        (ie broken), because this should not vary too much between
154        (subsequent?) pages in a book.  */
155     vfill = 0;
156
157   if (Stencil *s = unsmob_stencil (p->header_))
158     {
159       stencil = stack_stencils (stencil, *s, &o);
160       o[Y_AXIS] += p->paper_->get_dimension (ly_symbol2scm ("head-sep"));
161     }
162
163   for (SCM s = p->lines_; s != SCM_EOL; s = ly_cdr (s))
164     {
165       Paper_line *p = unsmob_paper_line (ly_car (s));
166       stencil = stack_stencils (stencil, p->to_stencil (), &o);
167       /* Do not put vfill between title and its music, */
168       if (ly_cdr (s) != SCM_EOL
169           && (!p->is_title () || vfill < 0))
170         o[Y_AXIS] += vfill;
171       /* rather put extra just before the title.  */
172       if (ly_cdr (s) != SCM_EOL
173           && (unsmob_paper_line (ly_cadr (s))->is_title () && vfill > 0))
174         o[Y_AXIS] += vfill;
175     }
176
177   o[Y_AXIS] = p->paper_->get_dimension (ly_symbol2scm ("vsize"))
178     - p->paper_->get_dimension (ly_symbol2scm ("bottom-margin"));
179   if (unsmob_stencil (p->copyright_))
180     o[Y_AXIS] -= unsmob_stencil (p->copyright_)->extent (Y_AXIS).length ();
181   if (unsmob_stencil (p->tagline_))
182     o[Y_AXIS] -= unsmob_stencil (p->tagline_)->extent (Y_AXIS).length ();
183   if (unsmob_stencil (p->footer_))
184     o[Y_AXIS] -= unsmob_stencil (p->footer_)->extent (Y_AXIS).length ();
185
186   if (Stencil *s = unsmob_stencil (p->copyright_))
187     stencil = stack_stencils (stencil, *s, &o);
188   if (Stencil *s = unsmob_stencil (p->tagline_))
189     stencil = stack_stencils (stencil, *s, &o);
190   if (Stencil *s = unsmob_stencil (p->footer_))
191     stencil = stack_stencils (stencil, *s, &o);
192
193   return stencil.smobbed_copy ();
194 }
195
196 Real
197 Page::text_height () const
198 {
199   Real h = paper_->get_dimension (ly_symbol2scm ("vsize"))
200     - paper_->get_dimension (ly_symbol2scm ("top-margin"))
201     - paper_->get_dimension (ly_symbol2scm ("bottom-margin"));
202   if (unsmob_stencil (header_))
203     h -= unsmob_stencil (header_)->extent (Y_AXIS).length ()
204       + paper_->get_dimension (ly_symbol2scm ("head-sep"));
205   if (unsmob_stencil (copyright_)
206       || unsmob_stencil (tagline_)
207       || unsmob_stencil (footer_))
208     h -= paper_->get_dimension (ly_symbol2scm ("foot-sep"));
209   if (unsmob_stencil (copyright_))
210     h -= unsmob_stencil (copyright_)->extent (Y_AXIS).length ();
211   if (unsmob_stencil (tagline_))
212     h -= unsmob_stencil (tagline_)->extent (Y_AXIS).length ();
213   if (unsmob_stencil (footer_))
214     h -= unsmob_stencil (footer_)->extent (Y_AXIS).length ();
215   return h;
216 }
217
218 LY_DEFINE (ly_page_paper_lines, "ly:page-paper-lines",
219            1, 0, 0, (SCM page),
220            "Return paper-lines from PAGE.")
221 {
222   Page *p = unsmob_page (page);
223   SCM_ASSERT_TYPE (p, page, SCM_ARG1, __FUNCTION__, "page");
224   return p->lines_;
225 }