+1.5.4.jcn2
+==========
+
+* Spelling fixes, notably staffs->staves, except for ChangeLogs.
+
+* Removed `Default' from accidental comment names.
+
+* Compile fixes.
+
+* Fixed off by one error for point and click.
+
+* Website fixes, found bug in grace note stem lengths.
+
+1.5.4.hwn1
+==========
+
+* Ancient font update [WARNING FONTS CHANGED!] (Juergen Reuter)
+
+* New_spacing_spanner: revised spacing generation.
+
+* Default neutral direction set to down.
+
+* Junk hash table from flowerlib
+
+* Bugfix: grace nesting error
+
+* Bugfix: don't try schedule next bar when were on a grace moment.
+
+* Bugfix: set measurePosition especially for music starting with
+grace.
+
1.5.3.hwn1
==========
Rational div_rat (Rational) const;
Rational mod_rat (Rational) const;
void negate ();
- operator bool () const;
- operator int () const;
+ // operator bool () const;
+ int to_int () const;
operator double () const;
Rational operator - () const;
/**
#include "string-convert.hh"
#include "libc-extension.hh"
-Rational::operator bool () const
-{
- return sign_;
-}
-
-Rational::operator int () const
-{
- return sign_ * num_ / den_;
-}
-
Rational::operator double () const
{
return (double)sign_ * num_ / den_;
--- /dev/null
+
+\score { \notes \relative c'' {
+ f1
+ \grace e8 f1
+ < { \grace { e8 } f1 } >
+}
+}
--- /dev/null
+
+\header {
+texidoc = "Accidentals in different staffs don't effect the
+spacing of the quarter notes here."
+}
+
+\score { \notes \relative c'' < \context Staff = SA {
+c4 c4 cis4 cis4
+c4 c4 c4 c
+
+
+ }
+ { \key d \major c2 c2 c2 cis2 } >
+
+ \paper { linewidth = -1. }
+ }
+
+
--- /dev/null
+
+\header {
+texidoc = "Accidentals sticking out to the left
+of a note will take a little more space."
+}
+
+\score { \notes \relative c'' { c4 c cis4
+}
+\paper { linewidth = -1. }
+
+}
+
--- /dev/null
+
+\header {
+texidoc = "If possible clef changes and the like
+should be folded under notes of the different staff
+"
+}
+
+\score { \notes \relative c'' < \context Staff = SA {
+c4 c16 c c c cis4 cis4
+c4 c4 c4 c
+
+
+ }
+ { \key d \major c2
+ \clef bass
+ c,2 c cis2 } >
+
+ \paper { linewidth = -1. }
+ }
+
+
In a limited number of cases, LilyPond corrects for optical spacing
effects. In this example, space for opposite pointed stems is adjuste
"
+
}
+
\score {
\context Voice \notes\relative c {
\paper {
linewidth=-1.0
}
- \midi { }
}
+
+\score {
+ \context Voice \notes\relative c {
+
+ \time 12/4 c''4 c c c a f' f, a
+
+ }
+ \paper {
+ linewidth=-1.0
+ \translator { \ScoreContext
+ SpacingSpanner \override #'stem-spacing-correction = #0.0
+ } }
+}
+
\ No newline at end of file
cis] }
\translator Staff = bass
- \shiftOff
+ \shiftOff \stemUp
[bis gis] cis4 |
dis2 cis4 r8 cis }
\context Voice = one { \stemUp bis2 }
function = gh_list (ly_symbol2scm ("end"), SCM_UNDEFINED);
Moment one_beat = *unsmob_moment (get_property ("beatLength"));
- int num = *unsmob_moment (get_property ("measureLength")) / one_beat;
+ int num = int ((*unsmob_moment (get_property ("measureLength")) / one_beat).main_part_);
int den = one_beat.den ();
SCM time = gh_list (gh_int2scm (num), gh_int2scm (den), SCM_UNDEFINED);
moment = * unsmob_moment (gh_cdr (m));
Rational r;
- if (moment)
+ if (moment.to_bool ())
{
/* Ugh? measurePosition can be negative, when \partial
We may have to fix this elsewhere (timing translator)
Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
if (gh_number_p (bn) &&
- !mp && now_mom () > Moment (0))
+ !mp.to_bool () && now_mom () > Moment (0))
{
create_items ();
/*
ugh: need to share code with mark_engraver
*/
- daddy_trans_l_->set_property ("staffsFound", SCM_EOL);
+ daddy_trans_l_->set_property ("stavesFound", SCM_EOL);
}
Grob * s = inf.elem_l_;
if (Staff_symbol::has_interface (s))
{
- SCM sts = get_property ("staffsFound");
+ SCM sts = get_property ("stavesFound");
SCM thisstaff = inf.elem_l_->self_scm ();
if (scm_memq (thisstaff, sts) == SCM_BOOL_F)
- daddy_trans_l_->set_property ("staffsFound", gh_cons (thisstaff, sts));
+ daddy_trans_l_->set_property ("stavesFound", gh_cons (thisstaff, sts));
}
else if (text_p_
&& dynamic_cast<Item*> (s)
{
if (text_p_)
{
- text_p_->set_grob_property ("side-support-elements", get_property ("staffsFound"));
+ text_p_->set_grob_property ("side-support-elements", get_property ("stavesFound"));
typeset_grob (text_p_);
text_p_ =0;
}
void
Chord_tremolo_iterator::process (Moment m)
{
- if (!m)
+ if (!m.to_bool () )
{
Music_iterator *yeah = try_music (music_l ());
if (yeah)
void
Folded_repeat_iterator::process (Moment m)
{
- if (!m)
+ if (!m.to_bool () )
{
bool success = try_music (music_l ());
if (!success)
{
if (iter-> ok ())
prev_mom_ = now_mom_ = iter->pending_moment ();
-
+
+
+ bool first = true;
while (iter->ok () || moments_left_i ())
{
Moment w;
}
w = sneaky_insert_extra_moment (w);
+
+ // cout << "Proccing " << w << endl;
+
+
+ if (first)
+ {
+ first = false;
+ set_property (ly_symbol2scm ("measurePosition"), w.smobbed_copy ());
+ }
+
prepare (w);
if (iter->ok ())
iter->process (w);
Rational grace_part_;
void set_infinite (int k);
-
- operator bool ();
+
+ bool to_bool () const;
int den () const;
int num () const;
/*
SCM smobbed_copy () const;
String str () const;
static int compare (Moment const&, Moment const&);
+
};
IMPLEMENT_ARITHMETIC_OPERATOR (Moment, + );
IMPLEMENT_ARITHMETIC_OPERATOR (Moment, - );
IMPLEMENT_ARITHMETIC_OPERATOR (Moment, / );
IMPLEMENT_ARITHMETIC_OPERATOR (Moment, * );
+ostream & operator << ( ostream &,Moment const &);
Moment * unsmob_moment (SCM);
int compare (Moment const&,Moment const&);
--- /dev/null
+/*
+ spacing-spanner.hh -- declare New_spacing_spanner
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 1999--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+
+ */
+
+#ifndef SPACING_SPANNER_HH
+#define SPACING_SPANNER_HH
+
+#include "spanner.hh"
+#include "spring.hh"
+
+class New_spacing_spanner
+{
+public:
+ static void set_interface (Grob*);
+ static void do_measure (Grob*,Link_array<Grob> const &) ;
+ static void stretch_to_regularity (Grob*, Array<Spring> *, Link_array<Grob> const &);
+ static void breakable_column_spacing (Item* l, Item *r);
+ DECLARE_SCHEME_CALLBACK (set_springs, (SCM ));
+ static Real stem_dir_correction (Grob*,Grob*,Grob*) ;
+ static Real default_bar_spacing (Grob*,Grob*,Grob*,Moment) ;
+ static Real note_spacing (Grob*,Grob*,Grob*,Moment) ;
+ static Real get_duration_space (Grob*,Moment dur, Moment shortest) ;
+};
+
+#endif /* SPACING_SPANNER_HH */
+
*/
kpse_set_program_name (av0, NULL);
kpse_maketex_option ("tfm", TRUE);
-
-#if 0
-
-
- /*
-
- Remove the setting for TFMFONTS if we have kpathsea, because
- kpathsea can find TFM fonts anyway.
-
- If we don't lily will want to make tfms for cmr fonts, even if
- there is a :: entry in the TFMFONTS path.
-
- This will fail if a user has special fonts (outside of feta) that
- can not be found by kpath.
-
- If TFMFONTS is unset, TFMs of feta will be generated on the
- fly. The risk is that this will cause checksum mismatch errors,
- but MF is reasonably deterministic (so we hope not).
-
- The advantage is that the PK font will also be generated under
- /var/texmf/fonts, reducing clutter and compilation time.
-
- */
-
-#ifndef __CYGWIN__ /* mktextfm/mktexpk does not work on windows */
- unsetenv ("TFMFONTS");
-#endif
-
-#ifdef DEBIAN
- String my_tfm = "$VARTEXFONTS/tfm/public/lilypond";
-#else
- String my_tfm = "$VARTEXFONTS/tfm/lilypond/";
- my_tfm += version_str () + "/";
-#endif
-
-#ifdef DEBIAN
- char * mypath = strdup ((my_tfm + ":").ch_C());
- kpse_format_info[kpse_tfm_format].client_path = mypath;
-#else
- char * mypath = kpse_expand (my_tfm.ch_C ());
-
- String prog = "mktextfm --destdir ";
- prog += mypath;
-
- kpse_format_info[kpse_tfm_format].program = strdup (prog.ch_C ());
-#endif
#endif
-#endif
-
}
daddy_trans_l_->set_property ("localKeySignature", ly_deep_copy (sig));
last_keysig_ = sig;
}
- else if (!mp)
+ else if (!mp.to_bool () )
{
if (!to_boolean (get_property ("noResetKey")))
daddy_trans_l_->set_property ("localKeySignature", ly_deep_copy (sig));
{
Moment w = *unsmob_moment (scope_p_->scm_elem ("whole-in-seconds"));
Moment wholes_per_min = Moment (60) /w;
- int beats_per_min = wholes_per_min / one_beat_mom;
+ int beats_per_min = int ((wholes_per_min / one_beat_mom).main_part_);
return int (beats_per_min);
}
int
compare (Midi_note_event const& left, Midi_note_event const& right)
{
- return sign (left.key - right.key);
+ Moment m = (left.key - right.key);
+
+ if (m<0)
+ return -1;
+ else if (m > 0)
+ return 1;
+ else
+ return 0;
}
Midi_walker::Midi_walker (Audio_staff* audio_staff_l, Midi_track* track_l)
//midi_p->channel_i_ = track_l_->number_i_;
if (Midi_note* note_p = dynamic_cast<Midi_note*> (midi_p))
{
- if (note_p->length_mom ())
+ if (note_p->length_mom ().to_bool ())
do_start_note (note_p);
}
else
int
Moment::num () const { return main_part_.num (); }
-
-Moment::operator bool ()
+bool
+Moment::to_bool () const
{
return main_part_ || grace_part_;
}
}
Moment
-Moment::operator - ( ) const
+Moment::operator - () const
{
Moment m;
m.grace_part_ = -grace_part_;
m.main_part_ = -main_part_;
return m;
}
+
+ostream &
+operator << (ostream &os, Moment const &m)
+{
+ os << m.str ();
+ return os;
+}
Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
if (mmrest_p_ && (now_mom () >= start_moment_)
- && !mp
+ && !mp.to_bool ()
&& mmrest_p_->get_bound (LEFT) && mmrest_p_->get_bound (RIGHT))
{
typeset_grob (mmrest_p_);
SCM smp = get_property ("measurePosition");
Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
- if (mmrest_p_ && !mp)
+ if (mmrest_p_ && !mp.to_bool ())
{
lastrest_p_ = mmrest_p_;
int cur = gh_scm2int (get_property ("currentBarNumber"));
--- /dev/null
+/*
+ spacing-spanner.cc -- implement Spacing_spanner
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 1999--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+
+ */
+
+#include "new-spacing-spanner.hh"
+#include "paper-column.hh"
+#include "dimensions.hh"
+#include "paper-def.hh"
+#include "warn.hh"
+#include "paper-score.hh"
+#include "line-of-score.hh"
+#include "misc.hh"
+#include "separation-item.hh"
+
+
+void
+New_spacing_spanner::set_interface (Grob*me)
+{
+ me->set_extent_callback (SCM_EOL, X_AXIS);
+ me->set_extent_callback (SCM_EOL, Y_AXIS) ;
+}
+
+/*
+
+ The algorithm is partly taken from :
+
+ John S. Gourlay. ``Spacing a Line of Music,'' Technical Report
+ OSU-CISRC-10/87-TR35, Department of Computer and Information
+ Science, The Ohio State University, 1987.
+
+ TOO HAIRY.
+
+ TODO: write comments
+
+ */
+void
+New_spacing_spanner::do_measure (Grob*me, Link_array<Grob> const & cols)
+{
+ Moment shortest;
+ Moment mean_shortest;
+
+ /*
+ space as if this duration is present.
+ */
+ Moment base_shortest_duration = *unsmob_moment (me->get_grob_property ("maximum-duration-for-spacing"));
+ shortest.set_infinite (1);
+
+ int n = 0;
+ for (int i =0 ; i < cols.size (); i++)
+ {
+ if (Paper_column::musical_b (cols[i]))
+ {
+ Moment *when = unsmob_moment (cols[i]->get_grob_property ("when"));
+
+ /*
+ ignore grace notes for shortest notes.
+ */
+ if (when && when->grace_part_)
+ continue;
+
+ SCM st = cols[i]->get_grob_property ("shortest-starter-duration");
+ Moment this_shortest = *unsmob_moment (st);
+ shortest = shortest <? this_shortest;
+ if (!mean_shortest.main_part_.infty_b ())
+ {
+ n++;
+ mean_shortest += this_shortest;
+ }
+ }
+ }
+
+ Array<Spring> springs;
+
+ Item * first_col = 0;
+ for (int i= 0; i < cols.size () - 1; i++)
+ {
+ Item * l = dynamic_cast<Item*> (cols[i]);
+
+ if (!first_col && Paper_column::musical_b (l))
+ first_col = l;
+
+ SCM between = cols[i]->get_grob_property ("between-cols");
+ if (gh_pair_p (between)
+ && i > 0
+ && i < cols.size ()-1
+ && (gh_cdr (between) != cols[i+1]->self_scm ()
+ || gh_car (between) != cols[i-1]->self_scm ())
+ )
+ continue ;
+
+ int j = i+1;
+ for (; j < cols.size () - 1; j++)
+ {
+ if (Paper_column::musical_b (cols[j]))
+ break;
+
+ SCM between = cols[j]->get_grob_property ("between-cols");
+ if (!gh_pair_p (between))
+ continue;
+
+ if (gh_car (between) == cols[i]->self_scm () )
+ break ;
+ }
+
+ Item * r = dynamic_cast<Item*> (cols[j]);
+ Paper_column * lc = dynamic_cast<Paper_column*> (l);
+ Paper_column *rc = dynamic_cast<Paper_column*> (r);
+
+
+#if 0
+cout << "params for cols " << Paper_column::rank_i (l) << " " << Paper_column::rank_i (r) << endl;
+ cout << " musical: " << Paper_column::musical_b (l) << " " << Paper_column::musical_b (r) << endl;
+#endif
+
+ if (!Paper_column::musical_b (l))
+ {
+ breakable_column_spacing (l, r);
+
+ l = l->find_prebroken_piece (RIGHT);
+ if (l)
+ breakable_column_spacing (l,r);
+
+ continue ;
+ }
+
+ Real note_space = note_spacing (me,lc, rc, shortest <? base_shortest_duration);
+ Real hinterfleisch = note_space;
+ Real headwid = gh_scm2double (me->get_grob_property ("arithmetic-multiplier"));
+
+ for (SCM s = lc->get_grob_property ("spacing-sequence"); gh_pair_p (s); s = gh_cdr (s))
+ {
+ Grob *lm = unsmob_grob (gh_caar (s));
+ Grob *rm = unsmob_grob (gh_cdar (s));
+
+ // TODO; configgable.
+ hinterfleisch += -headwid + Separation_item::my_width (lm)[RIGHT] -
+ 0.5 * Separation_item::my_width (rm)[LEFT];
+
+
+ /*
+ UGH: KLUDGE!
+ */
+
+ // if (delta_t > Moment (1,32))
+ hinterfleisch += stem_dir_correction (me, l, r);
+ }
+
+ Real stretch_distance = note_space - headwid;
+ Spring s;
+ s.distance_f_ = hinterfleisch;
+ s.strength_f_ = 1 / stretch_distance;
+
+ s.item_l_drul_[LEFT] = l;
+ s.item_l_drul_[RIGHT] = r;
+
+ s.add_to_cols();
+ if (r->find_prebroken_piece (LEFT))
+ {
+ s.item_l_drul_[RIGHT] = r->find_prebroken_piece(LEFT);
+ s.add_to_cols();
+ }
+ }
+
+}
+
+/*
+ Read hints from L (todo: R) and generate springs.
+ */
+void
+New_spacing_spanner::breakable_column_spacing (Item* l, Item *r)
+{
+ Spring s;
+
+ Real break_dist = 0.0;
+ SCM espace = l->get_grob_property ("extra-space");
+ if (gh_pair_p (espace))
+ break_dist += gh_scm2double (gh_cdr (espace));
+
+ if (!break_dist)
+ break_dist = 1.0;
+
+ Real break_stretch = 0.0;
+
+ // todo: naming of "distance"
+ espace = l->get_grob_property ("stretch-distance");
+ if (gh_pair_p (espace))
+ break_stretch += gh_scm2double (gh_cdr (espace));
+
+ if (!break_stretch)
+ break_stretch = 1.0;
+
+ s.distance_f_ = break_dist;
+ s.strength_f_ = 1/break_stretch;
+ s.item_l_drul_[LEFT] = l;
+ s.item_l_drul_[RIGHT] = r;
+
+ s.add_to_cols ();
+}
+
+/*
+ Look at COLS, searching for columns that have 'regular-distance-to
+ set. A sequence of columns that have this property set should have
+ an equal distance (an equispaced run). Extract the projected
+ distance from SPRINGS, and scale SPRINGS for the equispaced run, to the
+ widest space necessary.
+
+
+ TODO:
+
+ -- inefficient code; maybe it is easier to twiddle with the springs
+ after they've become grob properties (ie. have their
+ minimum-distances set)
+
+ -- does not adjust strength field of the springs very well: result
+ awkward spacing at the start of a line. (?)
+
+ -- will be confused when there are multiple equispaced runs in a measure.
+
+ -- dealing with springs for line breaks is a little tricky; in any
+ case, we will only space per measure.
+
+ -- we scale to actual distances, not to optical effects. Eg. if the
+ equispaced run contains optical corrections, then the scaling will
+ cancel those.
+
+ -- Regular_spacing_engraver doesn't mark the first column of the
+ next bar, making the space before a barline too short, in this case
+
+
+ x<- 16ths--> x(8th)
+ x(8th) x(8th) <- equispaced run.
+
+*/
+
+void
+New_spacing_spanner::stretch_to_regularity (Grob *me,
+ Array<Spring> * springs,
+ Link_array<Grob> const & cols)
+{
+ /*
+ Find the starting column of the run. REGULAR-DISTANCE-TO points
+ back to a previous column, so we look ahead to find a column
+ pointing back to the first one.
+
+ */
+ Grob * first_regular_spaced_col = 0;
+ for (int i = 0 ; i < cols.size () && !first_regular_spaced_col; i++)
+ {
+ SCM rdt = cols[i]->get_grob_property ("regular-distance-to");
+ if (cols.find_l (dynamic_cast<Item*> (unsmob_grob (rdt))))
+ first_regular_spaced_col = unsmob_grob (rdt);
+ }
+ for (int i = springs->size (); i-- ;)
+ springs->elem (i).set_to_cols ();
+
+ int i;
+ for (i = 0; i < springs->size ()
+ && springs->elem (i).item_l_drul_[RIGHT] != first_regular_spaced_col;
+ i++)
+ ;
+
+
+ if (i==springs->size ())
+ return ;
+
+ Real maxdist = 0.0;
+ Real dist =0.0;
+ Grob *last_col = first_regular_spaced_col;
+ Grob *last_regular_spaced_col = first_regular_spaced_col;
+
+
+ /*
+ find the max distance for this run.
+ */
+ for (int j = i; j < springs->size (); j++)
+ {
+ Spring *s = &(springs->elem_ref (j));
+ if (s->item_l_drul_[LEFT] != last_col)
+ continue;
+
+ dist += s->distance_f_;
+
+ last_col = s->item_l_drul_[RIGHT];
+ SCM rdt = last_col->get_grob_property ("regular-distance-to");
+ if (unsmob_grob (rdt) == last_regular_spaced_col)
+ {
+ maxdist = maxdist >? dist;
+ dist = 0.0;
+ last_regular_spaced_col = last_col;
+ }
+
+ }
+
+ /*
+ Scale the springs
+ */
+ dist =0.0;
+ last_col = first_regular_spaced_col;
+ last_regular_spaced_col = first_regular_spaced_col;
+ for (int j = i; j < springs->size (); j++)
+ {
+ Spring *s = &springs->elem_ref (j);
+ if (s->item_l_drul_[LEFT] != last_col)
+ continue;
+ dist += s->distance_f_;
+
+ last_col = s->item_l_drul_[RIGHT];
+ SCM rdt = last_col->get_grob_property ("regular-distance-to");
+ if (unsmob_grob (rdt) == last_regular_spaced_col)
+ {
+ do {
+ springs->elem_ref (i).distance_f_ *= maxdist / dist;
+ springs->elem_ref (i).strength_f_ *= dist / maxdist;
+ } while (i++ < j);
+ last_regular_spaced_col = last_col;
+ dist =0.0;
+ }
+ }
+}
+
+/**
+ Do something if breakable column has no spacing hints set.
+ */
+Real
+New_spacing_spanner::default_bar_spacing (Grob*me, Grob *lc, Grob *rc,
+ Moment shortest)
+{
+ Real symbol_distance = lc->extent (lc,X_AXIS)[RIGHT] ;
+ Real durational_distance = 0;
+ Moment delta_t = Paper_column::when_mom (rc) - Paper_column::when_mom (lc);
+
+ /*
+ ugh should use shortest_playing distance
+ */
+ if (delta_t.to_bool ())
+ {
+ durational_distance = get_duration_space (me, delta_t, shortest);
+ }
+
+ return symbol_distance >? durational_distance;
+}
+
+
+/**
+ Get the measure wide ant for arithmetic spacing.
+
+ @see
+ John S. Gourlay. ``Spacing a Line of Music,'' Technical Report
+ OSU-CISRC-10/87-TR35, Department of Computer and Information Science,
+ The Ohio State University, 1987.
+
+ */
+Real
+New_spacing_spanner::get_duration_space (Grob*me, Moment d, Moment shortest)
+{
+ Real log = log_2 (shortest.main_part_);
+ Real k = gh_scm2double (me->get_grob_property ("arithmetic-basicspace"))
+ - log;
+
+ Rational compdur = d.main_part_ + d.grace_part_ /Rational (3);
+
+ return (log_2 (compdur) + k) * gh_scm2double (me->get_grob_property ("arithmetic-multiplier"));
+}
+
+
+Real
+New_spacing_spanner::note_spacing (Grob*me, Grob *lc, Grob *rc,
+ Moment shortest)
+{
+ Moment shortest_playing_len = 0;
+ SCM s = lc->get_grob_property ("shortest-playing-duration");
+
+ // SCM s = lc->get_grob_property ("mean-playing-duration");
+ if (unsmob_moment (s))
+ shortest_playing_len = *unsmob_moment (s);
+
+ if (! shortest_playing_len.to_bool ())
+ {
+ programming_error ("can't find a ruling note at " + Paper_column::when_mom (lc).str ());
+ shortest_playing_len = 1;
+ }
+
+ if (! shortest.to_bool ())
+ {
+ programming_error ("no minimum in measure at " + Paper_column::when_mom (lc).str ());
+ shortest = 1;
+ }
+ Moment delta_t = Paper_column::when_mom (rc) - Paper_column::when_mom (lc);
+ Real dist = get_duration_space (me, shortest_playing_len, shortest);
+
+
+ /*
+ ugh: 0.1 is an arbitrary distance.
+ */
+ dist *= (double) (delta_t.main_part_ / shortest_playing_len.main_part_)
+ + 0.1 * (double) (delta_t.grace_part_ / shortest_playing_len.main_part_);
+
+
+
+ Moment *lm = unsmob_moment (lc->get_grob_property ("when"));
+ Moment *rm = unsmob_moment (rc->get_grob_property ("when"));
+
+ if (lm && rm)
+ {
+ if (lm->grace_part_ && rm->grace_part_)
+ dist *= 0.5;
+ else if (!rm->grace_part_ && lm->grace_part_)
+ dist *= 0.7;
+ }
+
+
+ return dist;
+}
+
+
+/**
+ Correct for optical illusions. See [Wanske] p. 138. The combination
+ up-stem + down-stem should get extra space, the combination
+ down-stem + up-stem less.
+
+ This should be more advanced, since relative heights of the note
+ heads also influence required correction.
+
+ Also might not work correctly in case of multi voices or staff
+ changing voices
+
+ TODO: lookup correction distances? More advanced correction?
+ Possibly turn this off?
+
+ TODO: have to check wether the stems are in the same staff.
+
+ This routine reads the DIR-LIST property of both its L and R arguments. */
+Real
+New_spacing_spanner::stem_dir_correction (Grob*me, Grob*l, Grob*r)
+{
+ SCM dl = l->get_grob_property ("dir-list");
+ SCM dr = r->get_grob_property ("dir-list");
+
+ if (scm_ilength (dl) != 1 || scm_ilength (dr) != 1)
+ return 0.;
+
+ dl = gh_car (dl);
+ dr = gh_car (dr);
+
+ assert (gh_number_p (dl) && gh_number_p (dr));
+ int d1 = gh_scm2int (dl);
+ int d2 = gh_scm2int (dr);
+
+ if (d1 == d2)
+ return 0.0;
+
+
+ Real correction = 0.0;
+ Real ssc = gh_scm2double (me->get_grob_property ("stem-spacing-correction"));
+
+ if (d1 && d2 && d1 * d2 == -1)
+ {
+ correction = d1 * ssc;
+ }
+ else
+ programming_error ("Stem directions not set correctly for optical correction");
+ return correction;
+}
+
+
+MAKE_SCHEME_CALLBACK (New_spacing_spanner, set_springs,1);
+SCM
+New_spacing_spanner::set_springs (SCM smob)
+{
+ Grob *me = unsmob_grob (smob);
+ Link_array<Grob> all (me->pscore_l_->line_l_->column_l_arr ()) ;
+
+ int j = 0;
+
+ for (int i = 1; i < all.size (); i++)
+ {
+ Grob *sc = all[i];
+ if (Item::breakable_b (sc))
+ {
+ Link_array<Grob> measure (all.slice (j, i+1));
+ do_measure (me, measure);
+ j = i;
+ }
+ }
+
+ /*
+ farewell, cruel world
+ */
+ me->suicide ();
+ return SCM_UNSPECIFIED;
+}
+
+
+
+/*
+ maximum-duration-for-spacing
+From: bf250@freenet.carleton.ca (John Sankey)
+To: gnu-music-discuss@gnu.org
+Subject: note spacing suggestion
+Date: Mon, 10 Jul 2000 11:28:03 -0400 (EDT)
+
+Currently, Lily spaces notes by starting with a basic distance,
+arithmetic_multiplier, which it applies to the minimum duration note
+of the bar. Then she adds a logarithmic increment, scaled from
+arithmetic_basicspace, for longer notes. (Then, columns are aligned
+and justified.) Fundamentally, this matches visual spacing to musical
+weight and works well.
+
+A lot of the time in music, I see a section basically in melodic
+notes that occasionally has a rapid ornamental run (scale). So, there
+will be a section in 1/4 notes, then a brief passage in 1/32nds, then
+a return to long notes. Currently, Lily gives the same horizontal
+space to the 1/32nd notes in their bar (even if set in small size as
+is commonly done for cadenzii) as she gives to 1/4 notes in bars
+where 1/4 note is the minimum duration. The resulting visual weight
+does not match the musical weight over the page.
+
+Looking at the music I am typesetting, I feel that Lily's spacing
+could be significantly improved if, with no change in the basic
+method used, arithmetic_multiplier could be applied referred to the
+same duration throughout a piece. Of course, the current method
+should be retained for those who have already set music in it, so I
+suggest a property called something like arithmetic_base=16 to fix
+1/16 duration as the reference for arithmetic_multiplier; the default
+would be a dynamic base is it is now.
+
+Does anyone else feel that this would be a useful improvement for
+their music? (Of course, if arithmetic_multiplier became a regular
+property, this could be used to achieve a similar result by
+tweaking.)
+
+ */
class Note_heads_engraver : public Engraver
{
Link_array<Item> note_p_arr_;
+
Link_array<Item> dot_p_arr_;
Link_array<Note_req> note_req_l_arr_;
Moment note_end_mom_;
for (int i=0; i < note_p_arr_.size (); i++)
{
Audio_note* n = note_p_arr_[i];
- if (Moment m= n->delayed_until_mom_)
+ Moment m= n->delayed_until_mom_;
+ if (m.to_bool ())
{
global_l->add_moment_to_process (m);
delayed_p_arr_.push (n);
void
Percent_repeat_iterator::process (Moment m)
{
- if (!m)
+ if (!m.to_bool ())
{
Music_iterator *yeah = try_music (music_l ());
if (yeah)
find_rods (rb, gh_cdr (s));
}
+#if 0
+ /*
+ TODO; restore this.
+ */
/*
We've done our job, so we get lost.
*/
it->suicide ();
}
me->suicide ();
+#endif
return SCM_UNSPECIFIED ;
}
{
protected:
Item * break_malt_p_;
- Item * nobreak_malt_p_;
+ Item * musical_malt_p_;
+
+ /*
+ malt_p_ : we used to have a Single_malt_grouping_item
+
+ */
+ Item * last_step_musical_malt_p_;
+
Spanner * sep_span_p_;
virtual void acknowledge_grob (Grob_info);
Separating_line_group_engraver::Separating_line_group_engraver ()
{
+ last_step_musical_malt_p_ = 0;
sep_span_p_ = 0;
break_malt_p_ = 0;
- nobreak_malt_p_ =0;
+ musical_malt_p_ =0;
}
void
bool ib =Item::breakable_b (it);
Item *&p_ref_ (ib ? break_malt_p_
- : nobreak_malt_p_);
+ : musical_malt_p_);
if (!p_ref_)
{
typeset_grob (break_malt_p_);
break_malt_p_ =0;
}
- if (nobreak_malt_p_)
- {
- Separating_group_spanner::add_spacing_unit (sep_span_p_, nobreak_malt_p_);
- typeset_grob (nobreak_malt_p_);
- nobreak_malt_p_ =0;
- }
+
+ if (musical_malt_p_)
+ {
+ Separating_group_spanner::add_spacing_unit (sep_span_p_, musical_malt_p_);
+
+ if (last_step_musical_malt_p_)
+ {
+ Paper_column *col =
+ last_step_musical_malt_p_->column_l();
+ SCM newtup = gh_cons (last_step_musical_malt_p_->self_scm (),
+ musical_malt_p_->self_scm ());
+ col->set_grob_property ("spacing-sequence",
+ gh_cons (newtup,
+ col->get_grob_property ("spacing-sequence")));
+ }
+
+ typeset_grob (musical_malt_p_);
+ }
+ last_step_musical_malt_p_ = musical_malt_p_;
+ musical_malt_p_ =0;
+
+
}
#include "music-list.hh"
#include "request-chord-iterator.hh"
+
+/*
+
+ TODO: handling of grace notes is excuisite pain. This handling
+ should be formally specified and then the implementation verified.
+
+*/
+
/*
Invariant for the data structure.
}
+/*
+
+
+ if (start_music.grace)
+ here.grace -= start_music.grace
+
+ last
+ if (len
+
+ */
+
Grace_skip *
get_grace_skips (SCM cursor)
{
- Moment here (0);
+ Moment here (0);
Moment last (-1);
Grace_skip *head = 0;
Grace_skip **tail = &head;
Moment l =mus->length_mom ();
Moment s = mus->start_mom ();
- if (s.grace_part_ && last >= Moment (0))
+ if (s.grace_part_)
{
- Grace_skip *p =new Grace_skip;
- p->start_ = last;
- p->length_ = (here - last).main_part_;
- p->grace_start_ = s.grace_part_;
- p->next_ = 0;
- *tail = p;
- tail = &(*tail)->next_;
+ if (last != Moment (-1))
+ {
+ Grace_skip *p =new Grace_skip;
+ p->start_ = last;
+ p->length_ = (here - last).main_part_;
+ p->grace_start_ = s.grace_part_;
+ p->next_ = 0;
+ *tail = p;
+ tail = &(*tail)->next_;
+ }
+
+ here.grace_part_ = s.grace_part_;
}
- if (l.main_part_)
+ if (l.to_bool())
{
- l.grace_part_ = Rational (0);
last = here;
here += l;
}
Moment start = iter_p_->music_start_mom ();
assert (!grace_skips_ || grace_skips_->start_ >= here_mom_);
- if (len.main_part_ && grace_skips_ && grace_skips_->start_ == here_mom_)
+ if (len.main_part_ && grace_skips_ &&
+ grace_skips_->start_.main_part_ == here_mom_.main_part_)
{
Moment sk;
sk.main_part_ = grace_skips_->length_;
if (grace_skips_ && here_mom_ == grace_skips_->start_
&& cp.main_part_ >= grace_skips_->length_)
{
- cp += here_mom_ ;
- cp.grace_part_ = grace_skips_->grace_start_;
- return cp;
+ cp += here_mom_ ;
+ cp.grace_part_ = grace_skips_->grace_start_;
+ return cp;
}
- /*
- Fix-up a grace note at the start of the music.
- */
+ /*
+ Fix-up a grace note at the start of the music.
+ */
return cp + here_mom_ - iter_p_->music_start_mom ();
}
}
else
{
- programming_error ("No spring between adjacent columns");
+ programming_error (_f("No spring between column %d and next one",
+ Paper_column::rank_i (cols[i])
+ ));
desc.hooke_f_ = 1.0;
desc.ideal_f_ = default_space_f_;
}
for (int i=0; i < playing_durations_.size (); i++)
{
Moment m = (playing_durations_[i].info_.req_l_)->length_mom ();
- if (m)
+ if (m.to_bool ())
{
shortest_playing = shortest_playing <? m;
}
for (int i=0; i < now_durations_.size (); i++)
{
Moment m = now_durations_[i].info_.req_l_->length_mom ();
- if (m)
+ if (m.to_bool ())
starter = starter <? m;
playing_durations_.insert (now_durations_[i]);
/*
ugh should use shortest_playing distance
*/
- if (delta_t)
+ if (delta_t.to_bool ())
{
durational_distance = get_duration_space (me, delta_t, shortest);
}
Real
Spacing_spanner::get_duration_space (Grob*me, Moment d, Moment shortest)
{
- Real log = log_2 (shortest);
+ Real log = log_2 (shortest.main_part_);
Real k = gh_scm2double (me->get_grob_property ("arithmetic-basicspace"))
- log;
-
- return (log_2 (d) + k) * gh_scm2double (me->get_grob_property ("arithmetic-multiplier"));
+
+ Rational compdur = d.main_part_ + d.grace_part_ / Rational (3);
+ return (log_2 (compdur) + k) * gh_scm2double (me->get_grob_property ("arithmetic-multiplier"));
}
if (unsmob_moment (s))
shortest_playing_len = *unsmob_moment (s);
- if (! shortest_playing_len)
+ if (! shortest_playing_len.to_bool ())
{
programming_error ("can't find a ruling note at " + Paper_column::when_mom (lc).str ());
shortest_playing_len = 1;
}
- if (! shortest)
+ if (! shortest.to_bool ())
{
programming_error ("no minimum in measure at " + Paper_column::when_mom (lc).str ());
shortest = 1;
for (int i=0; i < finished_dynamic_tuple_arr_.size (); i++)
{
Audio_dynamic_tuple* a = &finished_dynamic_tuple_arr_[i];
- Real volume = start_volume + dv * (Real) (a->mom_ - start_mom)
- / (Real)dt;
+ Real volume = start_volume + dv * (Real) (a->mom_ - start_mom).main_part_
+ / (Real)dt.main_part_;
a->audio_l_->volume_ = volume;
}
finished_dynamic_tuple_arr_.clear ();
SCM met = tempo_req_l_->get_mus_property ("metronome-count");
Duration *d = unsmob_duration (tempo_req_l_->get_mus_property ("duration"));
- audio_p_ = new Audio_tempo (d->length_mom () /
- Moment (1, 4)
- * Moment (gh_scm2int (met)));
+ Rational r = (d->length_mom () / Moment (1, 4) * Moment (gh_scm2int (met))).main_part_;
+
+ audio_p_ = new Audio_tempo (int (r));
Audio_element_info info (audio_p_, tempo_req_l_);
announce_element (info);
void
Time_scaled_music_iterator::process (Moment m)
{
- if (!m)
+ if (!m.to_bool ())
{
Music_iterator *yeah = try_music (music_l ());
if (yeah)
if (timb && allbars)
{
Moment barleft = (measure_length () - measure_position ());
-
- if (barleft > Moment (0))
- global_l->add_moment_to_process (now_mom () + barleft);
+ Moment now = now_mom ();
+
+ if (barleft > Moment (0)
+ /*
+ Hmm. We insert the bar moment every time we process a
+ moment. A waste of cpu?
+ */
+ && !now.grace_part_)
+ global_l->add_moment_to_process (now + barleft);
}
}
void
Timing_translator::initialize ()
{
- Moment m;
daddy_trans_l_->set_property ("timing" , SCM_BOOL_T);
daddy_trans_l_->set_property ("currentBarNumber" , gh_int2scm (1));
- daddy_trans_l_->set_property ("measurePosition", m.smobbed_copy ());
+
daddy_trans_l_->set_property ("timeSignatureFraction",
gh_cons (gh_int2scm (4), gh_int2scm (4)));
-
+ daddy_trans_l_->set_property ("measurePosition", Moment (0).smobbed_copy ());
daddy_trans_l_->set_property ("measureLength", Moment (1).smobbed_copy ());
daddy_trans_l_->set_property ("beatLength", Moment (1,4).smobbed_copy ());
}
}
while (!global_l);
- Moment dt = global_l->now_mom_ - global_l -> prev_mom_;
+ Moment now = global_l->now_mom_;
+ Moment dt = now - global_l -> prev_mom_;
if (dt < Moment (0))
{
programming_error ("Moving backwards in time");
dt = 0;
}
- if (!dt)
+ if (!dt.to_bool ())
return;
Moment measposp;
}
else
{
+ measposp = now;
daddy_trans_l_->set_property ("measurePosition", measposp.smobbed_copy ());
}
started_span_p_arr_[i] =0;
}
- if (tsd)
+ if (tsd.to_bool ())
span_stop_moments_[i] += tsd.main_part_;
}
void
Unfolded_repeat_iterator::process (Moment m)
{
- if (!m)
+ if (!m.to_bool ())
{
if (volta_b_)
add_repeat_command (ly_symbol2scm ("start-repeat"));
;;;;
;;;; source file of the GNU LilyPond music typesetter
;;;;
-;;;; (c) 1998--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+;;;; (c) 1998--20.301 Han-Wen Nienhuys <hanwen@cs.uu.nl>
;;;; Jan Nieuwenhuizen <janneke@gnu.org>
; distances are given in stafflinethickness (thicknesses) and
(thickness . 0.48) ; in staff-space
(before-line-breaking-callback . ,Beam::before_line_breaking)
(after-line-breaking-callback . ,Beam::after_line_breaking)
- (neutral-direction . 1)
+ (neutral-direction . -1)
(dir-function . ,beam-dir-majority)
(height-quants . ,default-beam-dy-quants)
(vertical-position-quant-function . ,default-beam-y-quants)
(Script . (
;; don't set direction here: it breaks staccato.
(molecule-callback . ,Script::brew_molecule)
- (padding . 0.3)
+ (padding . 0.29)
(X-offset-callbacks . (,Side_position_interface::centered_on_parent))
(before-line-breaking-callback . ,Script::before_line_breaking)
(meta . ,(grob-description "Script" script-interface side-position-interface font-interface))
(SpacingSpanner . (
(spacing-procedure . ,Spacing_spanner::set_springs)
(stem-spacing-correction . 0.5)
+
+
+ ;; TODO: change naming -- unintuitive
(arithmetic-basicspace . 2.0)
(arithmetic-multiplier . ,(* 0.9 1.32))
;; assume that notes at least this long are present.
(lengths . (3.5 3.5 3.5 4.5 5.0))
(stem-shorten . (0.5))
; if stem is on middle line, choose this direction.
- (neutral-direction . 1)
+ (neutral-direction . -1)
(X-offset-callbacks . (,Stem::off_callback))
(X-extent-callback . ,Stem::dim_callback)
(Y-extent-callback . ,Stem::height)
(grob-property-description 'dash-period number? "the length of one dash + white space.")
(grob-property-description 'dashed number? "[FIXME: use dash-period/dash length; see text-spanner] number representing the length of the dashes.")
(grob-property-description 'de-uglify-parameters list? "list of 3 real constants. They define the valid areas for the middle control points. Used in de_uglyfy. They are a bit empirical.")
-(grob-property-description 'neutral-direction dir? "Where to go if we're in the middle of the staff.")
+(grob-property-description 'neutral-direction dir? "Where to go if
+we're in the middle of the staff. [Ross] has the following to say
+about this: Some engravers consider the middle line neutral, and take
+the option of using either up- or down-stems for notes that fall on
+it. However, more up-to-date engraving no longer permits an option;
+now a down-stem is always appropriate.")
+
(grob-property-description 'delta-y number? "amount of ascension.")
(grob-property-description 'dependencies list? "list of score-grob pointers that indicate who to compute first for certain global passes.")
(grob-property-description 'details list? "alist of parameters for detailed grob behavior.")
(grob-property-description 'stem-end-position number? "Where does the stem end (the end is opposite to the support-head.")
(grob-property-description 'stem-length number? "length of stem.")
(grob-property-description 'stem-shorten list? "shorten stems in forced directions given flag multiplicity.")
-(grob-property-description 'stem-spacing-correction number? "optical correction amount.")
+(grob-property-description 'stem-spacing-correction number? "optical correction amount. [TODO: doco] ")
(grob-property-description 'stems list? "list of stem objects, corresponding to the notes that the arpeggio has to be before.")
(grob-property-description 'stretch-distance number-pair? "pair of distances.")
(grob-property-description 'style symbol? "a string determining what style of glyph is typeset. Valid choices depend on the function that is reading this property. .")