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