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