~ubuntu-branches/ubuntu/precise/lilypond/precise

« back to all changes in this revision

Viewing changes to lily/spacing-basic.cc

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Bushnell, BSG
  • Date: 2006-12-19 10:18:12 UTC
  • mfrom: (3.1.4 feisty)
  • Revision ID: james.westby@ubuntu.com-20061219101812-7awtjkp0i393wxty
Tags: 2.8.7-3
scripts/midi2ly.py: When setting DATADIR, find Lilypond python files
in the @TOPLEVEL_VERSION@ directory, not 'current'.  Patch thanks to
Chris Lamb (chris@chris-lamb.co.uk).  (Closes: #400550)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  spacing-basic.cc -- implement Spacing_spanner, simplistic spacing routines
 
3
 
 
4
  source file of the GNU LilyPond music typesetter
 
5
 
 
6
  (c) 2005--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
 
7
*/
 
8
 
 
9
#include "spacing-spanner.hh"
 
10
#include "moment.hh"
 
11
#include "paper-column.hh"
 
12
#include "misc.hh"
 
13
#include "warn.hh"
 
14
 
 
15
/*
 
16
  LilyPond spaces by taking a simple-minded spacing algorithm, and
 
17
  adding subtle adjustments to that. This file does the simple-minded
 
18
  spacing routines.
 
19
*/
 
20
 
 
21
/*
 
22
  Get the measure wide ant for arithmetic spacing.
 
23
*/
 
24
Real
 
25
Spacing_options::get_duration_space (Moment d,
 
26
                                     bool *expand_only) const
 
27
{
 
28
  Real k = shortest_duration_space_;
 
29
 
 
30
  if (d < global_shortest_)
 
31
    {
 
32
      /*
 
33
        We don't space really short notes using the log of the
 
34
        duration, since it would disproportionally stretches the long
 
35
        notes in a piece. In stead, we use geometric spacing with constant 0.5
 
36
        (i.e. linear.)
 
37
 
 
38
        This should probably be tunable, to use other base numbers.
 
39
 
 
40
        In Mozart hrn3 by EB., we have 8th note = 3.9 mm (total), 16th note =
 
41
        3.6 mm (total).  head-width = 2.4, so we 1.2mm for 16th, 1.5
 
42
        mm for 8th. (white space), suggesting that we use
 
43
 
 
44
        (1.2 / 1.5)^{-log2(duration ratio)}
 
45
 
 
46
 
 
47
      */
 
48
      Rational ratio = d.main_part_ / global_shortest_;
 
49
 
 
50
      return ((k - 1) + double (ratio)) * increment_;
 
51
    }
 
52
  else
 
53
    {
 
54
      /*
 
55
        John S. Gourlay. ``Spacing a Line of Music, '' Technical
 
56
        Report OSU-CISRC-10/87-TR35, Department of Computer and
 
57
        Information Science, The Ohio State University, 1987.
 
58
      */
 
59
      Real log = log_2 (global_shortest_);
 
60
      k -= log;
 
61
      Rational compdur = d.main_part_ + d.grace_part_ / Rational (3);
 
62
      *expand_only = false;
 
63
 
 
64
      return (log_2 (compdur) + k) * increment_;
 
65
    }
 
66
}
 
67
 
 
68
/*
 
69
  The one-size-fits all spacing. It doesn't take into account
 
70
  different spacing wishes from one to the next column.
 
71
*/
 
72
void
 
73
Spacing_spanner::standard_breakable_column_spacing (Grob *me, Item *l, Item *r,
 
74
                                                    Real *fixed, Real *space,
 
75
                                                    Spacing_options const *options)
 
76
{
 
77
  *fixed = 0.0;
 
78
  Direction d = LEFT;
 
79
  Drul_array<Item *> cols (l, r);
 
80
 
 
81
  do
 
82
    {
 
83
      if (!Paper_column::is_musical (cols[d]))
 
84
        {
 
85
          /*
 
86
            Tied accidentals over barlines cause problems, so lets see
 
87
            what happens if we do this for non musical columns only.
 
88
          */
 
89
          Interval lext = cols[d]->extent (cols [d], X_AXIS);
 
90
          if (!lext.is_empty ())
 
91
            *fixed += -d * lext[-d];
 
92
        }
 
93
    }
 
94
  while (flip (&d) != LEFT);
 
95
 
 
96
  if ((l->is_breakable (l) || l->original ())
 
97
      && (r->is_breakable (r) || r->original ()))
 
98
    {
 
99
      Moment *dt = unsmob_moment (l->get_property ("measure-length"));
 
100
      Moment mlen (1);
 
101
      if (dt)
 
102
        mlen = *dt;
 
103
 
 
104
      Real incr = robust_scm2double (me->get_property ("spacing-increment"), 1);
 
105
 
 
106
      *space = *fixed + incr * double (mlen.main_part_ / options->global_shortest_) * 0.8;
 
107
    }
 
108
  else
 
109
    {
 
110
      Moment dt = Paper_column::when_mom (r) - Paper_column::when_mom (l);
 
111
 
 
112
      if (dt == Moment (0, 0))
 
113
        {
 
114
          /*
 
115
            In this case, Staff_spacing should handle the job,
 
116
            using dt when it is 0 is silly.
 
117
          */
 
118
          *space = *fixed + 0.5;
 
119
        }
 
120
      else
 
121
        {
 
122
          bool dummy;
 
123
          *space = *fixed + options->get_duration_space (dt, &dummy);
 
124
        }
 
125
    }
 
126
}
 
127
 
 
128
Real
 
129
Spacing_spanner::note_spacing (Grob *me, Grob *lc, Grob *rc,
 
130
                               Spacing_options const *options,
 
131
                               bool *expand_only)
 
132
{
 
133
  Moment shortest_playing_len = 0;
 
134
  SCM s = lc->get_property ("shortest-playing-duration");
 
135
 
 
136
  if (unsmob_moment (s))
 
137
    shortest_playing_len = *unsmob_moment (s);
 
138
 
 
139
  if (! shortest_playing_len.to_bool ())
 
140
    {
 
141
      programming_error ("can't find a ruling note at " + Paper_column::when_mom (lc).to_string ());
 
142
      shortest_playing_len = 1;
 
143
    }
 
144
 
 
145
  Moment lwhen = Paper_column::when_mom (lc);
 
146
  Moment rwhen = Paper_column::when_mom (rc);
 
147
 
 
148
  Moment delta_t = rwhen - lwhen;
 
149
  if (!Paper_column::is_musical (rc))
 
150
    {
 
151
      /*
 
152
        when toying with mmrests, it is possible to have musical
 
153
        column on the left and non-musical on the right, spanning
 
154
        several measures.
 
155
      */
 
156
 
 
157
      Moment *dt = unsmob_moment (rc->get_property ("measure-length"));
 
158
      if (dt)
 
159
        {
 
160
          delta_t = min (delta_t, *dt);
 
161
 
 
162
          /*
 
163
            The following is an extra safety measure, such that
 
164
            the length of a mmrest event doesn't cause havoc.
 
165
          */
 
166
          shortest_playing_len = min (shortest_playing_len, *dt);
 
167
        }
 
168
    }
 
169
 
 
170
  Real dist = 0.0;
 
171
  if (delta_t.main_part_ && !lwhen.grace_part_)
 
172
    {
 
173
      dist = options->get_duration_space (shortest_playing_len,
 
174
                                          expand_only);
 
175
      dist *= double (delta_t.main_part_ / shortest_playing_len.main_part_);
 
176
    }
 
177
  else if (delta_t.grace_part_)
 
178
    {
 
179
      /*
 
180
        Crude hack for spacing graces: we take the shortest space
 
181
        available (namely the space for the global shortest note), and
 
182
        multiply that by grace-space-factor
 
183
      */
 
184
      dist = options->get_duration_space (options->global_shortest_, expand_only);
 
185
 
 
186
      Real grace_fact
 
187
        = robust_scm2double (me->get_property ("grace-space-factor"), 1);
 
188
 
 
189
      dist *= grace_fact;
 
190
    }
 
191
 
 
192
  return dist;
 
193
}
 
194
 
 
195
/****************************************************************/
 
196
 
 
197
void
 
198
Spacing_options::init_from_grob (Grob *me)
 
199
{
 
200
  increment_ = robust_scm2double (me->get_property ("spacing-increment"), 1);
 
201
 
 
202
  packed_ = to_boolean (me->get_property ("packed-spacing"));
 
203
  stretch_uniformly_ = to_boolean (me->get_property ("uniform-stretching"));
 
204
  float_nonmusical_columns_
 
205
    = to_boolean (me->get_property ("strict-note-spacing"));
 
206
  shortest_duration_space_ = robust_scm2double (me->get_property ("shortest-duration-space"), 1);
 
207
}
 
208
 
 
209
void
 
210
Spacing_options::init ()
 
211
{
 
212
  increment_ = 1.2;
 
213
  packed_ = false;
 
214
  stretch_uniformly_ = false;
 
215
  float_nonmusical_columns_ = false;
 
216
  shortest_duration_space_ = 2.0;
 
217
 
 
218
  global_shortest_ = Rational (1, 8);
 
219
}