]> git.donarmstrong.com Git - lilypond.git/blob - lily/output-def.cc
Run grand-replace (issue 3765)
[lilypond.git] / lily / output-def.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1997--2014 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
6   LilyPond is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   LilyPond is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "output-def.hh"
21
22 #include "context-def.hh"
23 #include "file-path.hh"
24 #include "global-context.hh"
25 #include "international.hh"
26 #include "interval.hh"
27 #include "main.hh"
28 #include "output-def.hh"
29 #include "scm-hash.hh"
30 #include "warn.hh"
31
32 #include "ly-smobs.icc"
33
34 #include "program-option.hh"
35
36 #include "string-convert.hh"
37
38 Output_def::Output_def ()
39 {
40   scope_ = SCM_EOL;
41   parent_ = 0;
42
43   smobify_self ();
44
45   scope_ = ly_make_module (false);
46 }
47
48 Output_def::Output_def (Output_def const &s)
49 {
50   scope_ = SCM_EOL;
51   parent_ = 0;
52   smobify_self ();
53
54   input_origin_ = s.input_origin_;
55   scope_ = ly_make_module (false);
56   if (ly_is_module (s.scope_))
57     ly_module_copy (scope_, s.scope_);
58 }
59
60 Output_def::~Output_def ()
61 {
62 }
63
64 IMPLEMENT_SMOBS (Output_def);
65 IMPLEMENT_DEFAULT_EQUAL_P (Output_def);
66
67 SCM
68 Output_def::mark_smob (SCM m)
69 {
70   Output_def *mo = (Output_def*) SCM_CELL_WORD_1 (m);
71
72   /* FIXME: why is this necessary?
73      all paper_ should be protected by themselves. */
74   if (mo->parent_)
75     scm_gc_mark (mo->parent_->self_scm ());
76
77   return mo->scope_;
78 }
79
80 void
81 assign_context_def (Output_def * m, SCM transdef)
82 {
83   Context_def *tp = unsmob_context_def (transdef);
84   assert (tp);
85
86   if (tp)
87     {
88       SCM sym = tp->get_context_name ();
89       m->set_variable (sym, transdef);
90     }
91 }
92
93 /* find the translator for NAME. NAME must be a symbol. */
94 SCM
95 find_context_def (Output_def const *m, SCM name)
96 {
97   Context_def *cd = unsmob_context_def (m->lookup_variable (name));
98   return cd ? cd->self_scm () : SCM_EOL;
99 }
100
101 int
102 Output_def::print_smob (SCM s, SCM p, scm_print_state *)
103 {
104   Output_def * def = unsmob_output_def (s);
105   scm_puts ("#< ", p);
106   scm_puts (def->class_name (), p);
107   scm_puts (">", p);
108   return 1;
109 }
110
111 Real
112 Output_def::get_dimension (SCM s) const
113 {
114   SCM val = lookup_variable (s);
115   return scm_to_double (val);
116 }
117
118 SCM
119 Output_def::lookup_variable (SCM sym) const
120 {
121   SCM var = ly_module_lookup (scope_, sym);
122   if (SCM_VARIABLEP (var) && SCM_VARIABLE_REF (var) != SCM_UNDEFINED)
123     return SCM_VARIABLE_REF (var);
124
125   if (parent_)
126     return parent_->lookup_variable (sym);
127
128   return SCM_UNDEFINED;
129 }
130
131 SCM
132 Output_def::c_variable (const string &s) const
133 {
134   return lookup_variable (ly_symbol2scm (s.c_str ()));
135 }
136
137 void
138 Output_def::set_variable (SCM sym, SCM val)
139 {
140   scm_module_define (scope_, sym, val);
141 }
142
143 void
144 Output_def::normalize ()
145 {
146   Real paper_width;
147   SCM scm_paper_width = c_variable ("paper-width");
148
149   bool twosided = to_boolean (c_variable ("two-sided"));
150   // We don't distinguish between outer-margin / left-margin and so on
151   // until page-stencil positioning in page.scm
152   Real left_margin, left_margin_default;
153   SCM scm_left_margin_default = (twosided
154                                  ? c_variable ("outer-margin-default-scaled")
155                                  : c_variable ("left-margin-default-scaled"));
156   SCM scm_left_margin = (twosided
157                          ? c_variable ("outer-margin")
158                          : c_variable ("left-margin"));
159
160   Real right_margin, right_margin_default;
161   SCM scm_right_margin_default = (twosided
162                                   ? c_variable ("inner-margin-default-scaled")
163                                   : c_variable ("right-margin-default-scaled"));
164   SCM scm_right_margin = (twosided
165                           ? c_variable ("inner-margin")
166                           : c_variable ("right-margin"));
167
168   if (scm_paper_width == SCM_UNDEFINED
169       || scm_left_margin_default == SCM_UNDEFINED
170       || scm_right_margin_default == SCM_UNDEFINED)
171     {
172       programming_error ("called normalize () on paper with missing settings");
173       return;
174     }
175   else
176     {
177       paper_width = scm_to_double (scm_paper_width);
178       left_margin_default = scm_to_double (scm_left_margin_default);
179       right_margin_default = scm_to_double (scm_right_margin_default);
180     }
181
182   Real line_width;
183   Real line_width_default
184     = paper_width - left_margin_default - right_margin_default;
185   SCM scm_line_width = c_variable ("line-width");
186
187   Real binding_offset = 0;
188   if (twosided)
189     binding_offset = robust_scm2double (c_variable ("binding-offset"), 0);
190
191   if (scm_line_width == SCM_UNDEFINED)
192     {
193       left_margin = ((scm_left_margin == SCM_UNDEFINED)
194                      ? left_margin_default
195                      : scm_to_double (scm_left_margin));
196       right_margin = ((scm_right_margin == SCM_UNDEFINED)
197                       ? right_margin_default
198                       : scm_to_double (scm_right_margin)) + binding_offset;
199       line_width = paper_width - left_margin - right_margin;
200     }
201   else
202     {
203       line_width = scm_to_double (scm_line_width);
204       if (scm_left_margin == SCM_UNDEFINED)
205         {
206           // Vertically center systems if only line-width is given
207           if (scm_right_margin == SCM_UNDEFINED)
208             {
209               left_margin = (paper_width - line_width) / 2;
210               right_margin = left_margin;
211             }
212           else
213             {
214               right_margin = scm_to_double (scm_right_margin) + binding_offset;
215               left_margin = paper_width - line_width - right_margin;
216             }
217         }
218       else
219         {
220           left_margin = scm_to_double (scm_left_margin);
221           right_margin = ((scm_right_margin == SCM_UNDEFINED)
222                            ? (paper_width - line_width - left_margin)
223                            : scm_to_double (scm_right_margin)) + binding_offset;
224         }
225     }
226
227   if (to_boolean (c_variable ("check-consistency")))
228     {
229       // Consistency checks. If values don't match, set defaults.
230       if (abs (paper_width - line_width - left_margin - right_margin) > 1e-6)
231         {
232           line_width = line_width_default;
233           left_margin = left_margin_default;
234           right_margin = right_margin_default;
235           warning (_ ("margins do not fit with line-width, setting default values"));
236         }
237       else if ((left_margin < 0) || (right_margin < 0))
238         {
239           line_width = line_width_default;
240           left_margin = left_margin_default;
241           right_margin = right_margin_default;
242           warning (_ ("systems run off the page due to improper paper settings, setting default values"));
243         }
244     }
245
246   set_variable (ly_symbol2scm ("left-margin"), scm_from_double (left_margin));
247   set_variable (ly_symbol2scm ("right-margin"), scm_from_double (right_margin));
248   set_variable (ly_symbol2scm ("line-width"), scm_from_double (line_width));
249 }
250
251 /* FIXME.  This is broken until we have a generic way of
252    putting lists inside the \layout block.  */
253 Interval
254 line_dimensions_int (Output_def *def, int n)
255 {
256   Real lw = def->get_dimension (ly_symbol2scm ("line-width"));
257   Real ind = n
258     ? def->get_dimension (ly_symbol2scm ("short-indent"))
259     : def->get_dimension (ly_symbol2scm ("indent"));
260   return Interval (ind, lw);
261 }
262
263