]> git.donarmstrong.com Git - lilypond.git/blob - lily/page.cc
3e0db3c82a8e5b4b8f96d99c3c662bf33f298f01
[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 "ly-module.hh"
10 #include "page.hh"
11 #include "paper-def.hh"
12 #include "paper-outputter.hh"
13 #include "paper-line.hh"
14 #include "stencil.hh"
15 #include "warn.hh"
16
17 // JUNKME
18 SCM
19 stencil2line (Stencil* stil, bool is_title = false)
20 {
21   static SCM z;
22   if (!z)
23     z = scm_permanent_object (ly_offset2scm (Offset (0, 0)));
24   Offset dim = Offset (stil->extent (X_AXIS).length (),
25                        stil->extent (Y_AXIS).length ());
26   Paper_line *pl = new Paper_line (dim, scm_cons (stil->smobbed_copy (),
27                                                   SCM_EOL),
28                                    -10001 * is_title, is_title);
29
30   return scm_gc_unprotect_object (pl->self_scm ());
31 }
32
33 static Real const MIN_COVERAGE = 0.66;
34
35 int Page::page_count_ = 0;
36
37 Page::Page (Paper_def *paper, int number)
38 {
39   paper_ = paper;
40   number_ = number;
41
42   copyright_ = SCM_EOL;
43   footer_ = SCM_EOL;
44   header_ = SCM_EOL;
45   lines_ = SCM_EOL;
46   tagline_ = SCM_EOL;
47   
48   height_ = 0;
49   line_count_ = 0;
50   
51   page_count_++;
52
53   hsize_ = paper->get_dimension (ly_symbol2scm ("hsize"));
54   vsize_ = paper->get_dimension (ly_symbol2scm ("vsize"));
55   top_margin_ = paper->get_dimension (ly_symbol2scm ("top-margin"));
56   bottom_margin_ = paper->get_dimension (ly_symbol2scm ("bottom-margin"));
57   head_sep_ = paper->get_dimension (ly_symbol2scm ("head-sep"));
58   foot_sep_ = paper->get_dimension (ly_symbol2scm ("foot-sep"));
59   text_width_ = paper->get_dimension (ly_symbol2scm ("linewidth"));
60   left_margin_ = (hsize_ - text_width_) / 2;
61   
62   SCM make_header = ly_scheme_function ("make-header");
63   SCM make_footer = ly_scheme_function ("make-footer");
64
65   header_ = scm_call_2 (make_header, paper_->self_scm (),
66                         scm_int2num (number_));
67   if (unsmob_stencil (header_))
68     unsmob_stencil (header_)->align_to (Y_AXIS, UP);
69     
70   footer_ = scm_call_2 (make_footer, paper_->self_scm (),
71                         scm_int2num (number_));
72   if (unsmob_stencil (footer_))
73     unsmob_stencil (footer_)->align_to (Y_AXIS, UP);
74
75   smobify_self ();
76 }
77
78 Page::~Page ()
79 {
80 }
81
82 #include "ly-smobs.icc"
83
84 IMPLEMENT_DEFAULT_EQUAL_P (Page)
85 IMPLEMENT_SMOBS (Page)
86 IMPLEMENT_TYPE_P (Page, "ly:page?")
87
88 SCM
89 Page::mark_smob (SCM smob)
90 {
91   Page *p = (Page*) SCM_CELL_WORD_1 (smob);
92   scm_gc_mark (p->lines_);
93   scm_gc_mark (p->header_);
94   scm_gc_mark (p->footer_);
95   scm_gc_mark (p->copyright_);
96   scm_gc_mark (p->tagline_);
97   return p->lines_;
98 }
99
100 int
101 Page::print_smob (SCM smob, SCM port, scm_print_state*)
102 {
103   Page *p = (Page*) ly_cdr (smob);
104      
105   scm_puts ("#<", port);
106   scm_puts (classname (p), port);
107   scm_puts (to_string (p->number_).to_str0 (), port);
108   scm_puts (" ", port);
109   scm_puts (">", port);
110   return 1;
111 }
112
113 void
114 Page::output (Paper_outputter *out, bool is_last)
115 {
116   progress_indication ("[" + to_string (number_));
117   out->output_scheme (scm_list_1 (ly_symbol2scm ("start-page")));
118   Offset o (left_margin_, top_margin_);
119   Real vfill = line_count_ > 1 ? (text_height () - height_) / (line_count_ - 1)
120     : 0;
121
122   Real coverage = height_ / text_height ();
123   if (coverage < MIN_COVERAGE)
124     /* Do not space out a badly filled page.  This is too simplistic
125        (ie broken), because this should not vary too much between
126        (subsequent?) pages in a book.  */
127     vfill = 0;
128
129   if (unsmob_stencil (header_))
130     {
131       out->output_line (stencil2line (unsmob_stencil (header_)), &o, false);
132       o[Y_AXIS] += head_sep_;
133     }
134   for (SCM s = lines_; s != SCM_EOL; s = ly_cdr (s))
135     {
136       SCM line = ly_car (s);
137       out->output_line (line, &o,
138                         is_last && ly_cdr (s) != SCM_EOL && !unsmob_stencil (copyright_)
139                         && !unsmob_stencil (tagline_) && !unsmob_stencil (footer_));
140       
141       /* Do not put vfill between title and its music, */
142       if (scm_pair_p (ly_cdr (s))
143           && (!unsmob_paper_line (line)->is_title () || vfill < 0))
144         o[Y_AXIS] += vfill;
145       /* rather put extra just before the title.  */
146       if (ly_cdr (s) != SCM_EOL
147           && (unsmob_paper_line (ly_cadr (s))->is_title () && vfill > 0))
148         o[Y_AXIS] += vfill;
149     }
150
151   o[Y_AXIS] = vsize_ - bottom_margin_;
152   if (unsmob_stencil (copyright_))
153     o[Y_AXIS] -= unsmob_stencil (copyright_)->extent (Y_AXIS).length ();
154   if (unsmob_stencil (tagline_))
155     o[Y_AXIS] -= unsmob_stencil (tagline_)->extent (Y_AXIS).length ();
156   if (unsmob_stencil (footer_))
157     o[Y_AXIS] -= unsmob_stencil (footer_)->extent (Y_AXIS).length ();
158
159   if (unsmob_stencil (copyright_))
160     out->output_line (stencil2line (unsmob_stencil (copyright_)), &o,
161                       is_last && !unsmob_stencil (tagline_) && !unsmob_stencil (footer_));
162   if (unsmob_stencil (tagline_))
163     out->output_line (stencil2line (unsmob_stencil (tagline_)), &o,
164                       is_last && !unsmob_stencil (footer_));
165   if (unsmob_stencil (footer_))
166     out->output_line (stencil2line (unsmob_stencil (footer_)), &o, is_last);
167   out->output_scheme (scm_list_2 (ly_symbol2scm ("stop-page"),
168                                   ly_bool2scm (is_last && !unsmob_stencil (footer_))));
169   progress_indication ("]");
170 }
171
172 Real
173 Page::text_height ()
174 {
175   Real h = vsize_ - top_margin_ - bottom_margin_;
176   if (unsmob_stencil (header_))
177     h -= unsmob_stencil (header_)->extent (Y_AXIS).length () + head_sep_;
178   if (unsmob_stencil (copyright_) || unsmob_stencil (tagline_) || unsmob_stencil (footer_))
179     h -= foot_sep_;
180   if (unsmob_stencil (copyright_))
181     h -= unsmob_stencil (copyright_)->extent (Y_AXIS).length ();
182   if (unsmob_stencil (tagline_))
183     h -= unsmob_stencil (tagline_)->extent (Y_AXIS).length ();
184   if (unsmob_stencil (footer_))
185     h -= unsmob_stencil (footer_)->extent (Y_AXIS).length ();
186   return h;
187 }