@top GNU LilyPond --- The music typesetter
@c HJJ: Info needs `@top', which is a synonym for `@unnumbered' in TeX.
-This is the user manual for GNU LilyPond 2.10.x series.
+This is the user manual for GNU LilyPond 2.11.x series.
@ifhtml
(See the bottom of this page for the exact version number).
@end ifhtml
PACKAGE_NAME=LilyPond
MAJOR_VERSION=2
MINOR_VERSION=11
-PATCH_LEVEL=3
+PATCH_LEVEL=4
MY_PATCH_LEVEL=
ORPHAN_GROB_PENALTY = 1
inspect_max_count = 0
+def shorten_string (s):
+ threshold = 15
+ if len (s) > 2*threshold:
+ s = s[:threshold] + '..' + s[-threshold:]
+ return s
+
def max_distance (x1, x2):
dist = 0.0
return tuple (map (int, m.groups ()))
- dest = os.path.join (dir, new.replace ('.png', '.compare.png'))
+ dest = os.path.join (dir, new.replace ('.png', '.compare.jpeg'))
try:
dims1 = png_dims (old)
dims2 = png_dims (new)
except AttributeError:
- os.link (new, dest)
+ ## hmmm. what to do?
+ system ('touch %(dest)s' % locals ())
return
dims = (min (dims1[0], dims2[0]),
system ("convert -depth 8 diff.png -blur 0x3 -negate -channel alpha,blue -type TrueColorMatte -fx 'intensity' matte.png")
- system ("composite -depth 8 -type Palette matte.png %(new)s %(dest)s" % locals ())
+ system ("composite -quality 65 matte.png %(new)s %(dest)s" % locals ())
class FileLink:
def __init__ (self):
</tr>
''' % (self.distance (), html_2,
cell (self.base_names[0], name),
- cell (self.base_names[1], name).replace ('.png', '.compare.png'))
+ cell (self.base_names[1], name).replace ('.png', '.compare.jpeg'))
return html_entry
file_link.add_file_compare (f1,f2)
def write_text_result_page (self, filename, threshold):
- print 'writing "%s"' % filename
out = None
if filename == '':
out = sys.stdout
else:
+ print 'writing "%s"' % filename
out = open_write_file (filename)
## todo: support more scores.
html += link.html_record_string (dir1, dir2)
+ short_dir1 = shorten_string (dir1)
+ short_dir2 = shorten_string (dir2)
html = '''<html>
<table rules="rows" border bordercolor="blue">
<tr>
<th>distance</th>
-<th>%(dir1)s</th>
-<th>%(dir2)s</th>
+<th>%(short_dir1)s</th>
+<th>%(short_dir2)s</th>
</tr>
%(html)s
</table>
global inspect_max_count
inspect_max_count = o.max_count
- compare_trees (a[0], a[1], os.path.join (a[1], 'compare-' + a[0]),
+ name = a[0].replace ('/', '')
+ name = shorten_string (name)
+
+ compare_trees (a[0], a[1], os.path.join (a[1], 'compare-' + name),
o.threshold)
if __name__ == '__main__':
#include "rational.hh"
#include <cmath>
+#include <cassert>
#include <cstdlib>
using namespace std;
Rational::operator double () const
{
- return ((double)sign_) * num_ / den_;
+ if (sign_ == -1 || sign_ == 1 || sign_ == 0)
+ return ((double)sign_) * num_ / den_;
+ if (sign_ == -2)
+ return -HUGE_VAL;
+ else if (sign_ == 2)
+ return HUGE_VAL;
+ else
+ assert (false);
+
+ return 0.0;
}
Rational::operator bool () const
--- /dev/null
+\header
+{
+ texidoc = "Beamlets in grace notes remain readable."
+}
+
+\version "2.10.2"
+\layout {
+ ragged-right = ##t
+}
+
+\relative c'
+\context Staff {
+ f1 \grace { a'8[ f16] } g1
+}
--- /dev/null
+
+\version "2.10.4"
+
+\header {
+
+ texidoc = "A @code{\\partial} may be combined with a
+ @code{\\grace}."
+
+}
+
+\score {
+ { \partial 4 \grace b8 b4 b1 }
+}
Direction event_dir = LEFT;
do
{
- Drul_array<bool> on_bound (j == 0 && event_dir==LEFT,
- j == segs.size() - 1 && event_dir==RIGHT);
- Drul_array<bool> inside (j > 0, j < segs.size()-1);
- bool event = on_bound[event_dir]
+ bool on_bound = (event_dir == LEFT) ? j == 0 :
+ j == segs.size() - 1;
+
+ bool inside_stem = (event_dir == LEFT)
+ ? segs[j].stem_index_ > 0
+ : segs[j].stem_index_ < stems.size () - 1;
+
+ bool event = on_bound
|| abs (segs[j].rank_ - segs[j+event_dir].rank_) > 1
|| (abs (vertical_count) >= segs[j].max_connect_
|| abs (vertical_count) >= segs[j + event_dir].max_connect_);
current.horizontal_[event_dir] = segs[j].stem_x_;
if (segs[j].dir_ == event_dir)
{
- if (on_bound[event_dir]
+ if (on_bound
&& me->get_bound (event_dir)->break_status_dir ())
{
current.horizontal_[event_dir]
Stem::duration_log (segs[j].stem_) == 1
? 1.98
: 1.32; // URG.
-
- if (inside[event_dir])
- notehead_width = min (notehead_width,
- fabs (segs[j+ event_dir].stem_x_
- - segs[j].stem_x_)/2);
-
+
+
+ if (inside_stem)
+ {
+ Grob *neighbor_stem = stems[segs[j].stem_index_ + event_dir];
+ Real neighbor_stem_x = neighbor_stem->relative_coordinate (commonx, X_AXIS);
+
+ notehead_width = min (notehead_width,
+ fabs (neighbor_stem_x - segs[j].stem_x_)/2);
+ }
current.horizontal_[event_dir] += event_dir * notehead_width;
}
}
Real width_;
Real stem_x_;
int rank_;
- int stem_index_;
+ vsize stem_index_;
bool gapped_;
Direction dir_;
int max_connect_;
void
Music_wrapper_iterator::do_quit ()
{
- child_iter_->quit ();
+ if (child_iter_)
+ child_iter_->quit ();
}
void
{
Music *my_music = get_music ();
Music *child = unsmob_music (my_music->get_property ("element"));
- child_iter_ = unsmob_iterator (get_iterator (child));
+ child_iter_ = (child)
+ ? unsmob_iterator (get_iterator (child))
+ : 0;
}
bool
void
Music_wrapper_iterator::process (Moment m)
{
- child_iter_->process (m);
+ if (child_iter_)
+ child_iter_->process (m);
}
Moment
Music_wrapper_iterator::pending_moment () const
{
- return child_iter_->pending_moment ();
+ if (child_iter_)
+ return child_iter_->pending_moment ();
+ else
+ return Music_iterator::pending_moment ();
}
IMPLEMENT_CTOR_CALLBACK (Music_wrapper_iterator);
bool
Music_wrapper_iterator::run_always () const
{
- return child_iter_->run_always ();
+ return (child_iter_ && child_iter_->run_always ());
}
{
Music *me = unsmob_music (m);
Music *elt = unsmob_music (me->get_property ("element"));
- return elt->start_mom ().smobbed_copy ();
+ if (elt)
+ return elt->start_mom ().smobbed_copy ();
+ else
+ return Moment ().smobbed_copy ();
}
MAKE_SCHEME_CALLBACK (Music_wrapper, length_callback, 1);
--- /dev/null
+/*
+ note-spacing-engraver.cc -- implement Note_spacing_engraver
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2006 Han-Wen Nienhuys <hanwen@lilypond.org>
+
+*/
+
+#include "engraver.hh"
+
+#include "item.hh"
+#include "pointer-group-interface.hh"
+
+#include "translator.icc"
+
+class Note_spacing_engraver : public Engraver
+{
+ Grob *last_spacing_;
+ Grob *spacing_;
+
+ void add_spacing_item (Grob *);
+
+ TRANSLATOR_DECLARATIONS (Note_spacing_engraver);
+protected:
+
+ DECLARE_ACKNOWLEDGER (rhythmic_grob);
+ DECLARE_ACKNOWLEDGER (note_column);
+ void stop_translation_timestep ();
+};
+
+Note_spacing_engraver::Note_spacing_engraver ()
+{
+ last_spacing_ = 0;
+ spacing_ = 0;
+}
+
+void
+Note_spacing_engraver::add_spacing_item (Grob *g)
+{
+ if (!spacing_)
+ {
+ spacing_ = make_item ("NoteSpacing", g->self_scm ());
+ }
+
+
+ if (spacing_)
+ {
+ Pointer_group_interface::add_grob (spacing_,
+ ly_symbol2scm ("left-items"),
+ g);
+
+ if (last_spacing_)
+ {
+ Pointer_group_interface::add_grob (last_spacing_,
+ ly_symbol2scm ("right-items"),
+ g);
+ }
+ }
+}
+
+
+void
+Note_spacing_engraver::acknowledge_note_column (Grob_info gi)
+{
+ add_spacing_item (gi.grob ());
+}
+
+void
+Note_spacing_engraver::acknowledge_rhythmic_grob (Grob_info gi)
+{
+ add_spacing_item (gi.grob ());
+}
+
+void
+Note_spacing_engraver::stop_translation_timestep ()
+{
+ if (spacing_)
+ {
+ last_spacing_ = spacing_;
+ spacing_ = 0;
+ }
+}
+
+ADD_ACKNOWLEDGER (Note_spacing_engraver, note_column);
+ADD_ACKNOWLEDGER (Note_spacing_engraver, rhythmic_grob);
+
+ADD_TRANSLATOR (Note_spacing_engraver,
+ /* doc */ "Generates NoteSpacing, an object linking horizontal lines for use in spacing.",
+ /* create */ "NoteSpacing",
+ /* read */ "",
+ /* write */ "");
Grob *note_column_;
Grob *dotcol_;
- Grob *last_spacing_;
- Grob *spacing_;
-
- void add_spacing_item (Grob *);
-
TRANSLATOR_DECLARATIONS (Rhythmic_column_engraver);
protected:
Rhythmic_column_engraver::Rhythmic_column_engraver ()
{
- spacing_ = 0;
- last_spacing_ = 0;
stem_ = 0;
note_column_ = 0;
dotcol_ = 0;
}
-void
-Rhythmic_column_engraver::add_spacing_item (Grob *g)
-{
- if (spacing_)
- {
- Pointer_group_interface::add_grob (spacing_,
- ly_symbol2scm ("left-items"),
- g);
- if (last_spacing_)
- {
- Pointer_group_interface::add_grob (last_spacing_,
- ly_symbol2scm ("right-items"),
- g);
- }
- }
-}
void
Rhythmic_column_engraver::process_acknowledged ()
{
if (!note_column_)
{
note_column_ = make_item ("NoteColumn", rheads_[0]->self_scm ());
-
- spacing_ = make_item ("NoteSpacing", SCM_EOL);
- add_spacing_item (note_column_);
}
for (vsize i = 0; i < rheads_.size (); i++)
Rhythmic_column_engraver::stop_translation_timestep ()
{
note_column_ = 0;
-
- if (spacing_)
- {
- last_spacing_ = spacing_;
- spacing_ = 0;
- }
-
dotcol_ = 0;
stem_ = 0;
}
ADD_TRANSLATOR (Rhythmic_column_engraver,
/* doc */ "Generates NoteColumn, an objects that groups stems, noteheads and rests.",
- /* create */ "NoteColumn NoteSpacing",
+ /* create */ "NoteColumn",
/* read */ "",
/* write */ "");
extract_grob_set (sys, "columns", cols);
- vsize col_idx = binary_search (cols, column,
- Paper_column::less_than);
-
- if (col_idx == VPOS)
- {
- programming_error ( __FUNCTION__ + string (": Unknown column"));
- return 0;
- }
+ vsize col_idx = Paper_column::get_rank (column);
do
{
Moment rwhen = Paper_column::when_mom (rc);
Moment delta_t = rwhen - lwhen;
- if (!Paper_column::is_musical (rc))
+
+ /*
+ when toying with mmrests, it is possible to have musical
+ column on the left and non-musical on the right, spanning
+ several measures.
+
+ TODO: efficiency: measure length can be cached, or stored as
+ property in paper-column.
+ */
+
+ if (Moment *measure_len = get_measure_length (lc))
{
+ delta_t = min (delta_t, *measure_len);
+
/*
- when toying with mmrests, it is possible to have musical
- column on the left and non-musical on the right, spanning
- several measures.
+ The following is an extra safety measure, such that
+ the length of a mmrest event doesn't cause havoc.
*/
-
- Moment *dt = get_measure_length (lc);
- if (dt)
- {
- delta_t = min (delta_t, *dt);
-
- /*
- The following is an extra safety measure, such that
- the length of a mmrest event doesn't cause havoc.
- */
- shortest_playing_len = min (shortest_playing_len, *dt);
- }
+ shortest_playing_len = min (shortest_playing_len, *measure_len);
}
Real dist = 0.0;
DECLARE_ACKNOWLEDGER (staff_spacing);
DECLARE_ACKNOWLEDGER (note_spacing);
DECLARE_ACKNOWLEDGER (rhythmic_head);
+ DECLARE_ACKNOWLEDGER (rhythmic_grob);
DECLARE_TRANSLATOR_LISTENER (spacing_section);
void start_translation_timestep ();
void stop_translation_timestep ();
void process_music ();
-
+ void add_starter_duration (Grob_info i);
+
virtual void finalize ();
void start_spanner ();
Pointer_group_interface::add_grob (spacing_, ly_symbol2scm ("wishes"), i.grob ());
}
+void
+Spacing_engraver::acknowledge_rhythmic_grob (Grob_info i)
+{
+ add_starter_duration (i);
+}
+
void
Spacing_engraver::acknowledge_rhythmic_head (Grob_info i)
+{
+ add_starter_duration (i);
+}
+
+
+void
+Spacing_engraver::add_starter_duration (Grob_info i)
{
if (i.grob ()->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface"))
|| i.grob ()->internal_has_interface (ly_symbol2scm ("multi-measure-interface")))
ADD_ACKNOWLEDGER (Spacing_engraver, staff_spacing);
ADD_ACKNOWLEDGER (Spacing_engraver, note_spacing);
ADD_ACKNOWLEDGER (Spacing_engraver, rhythmic_head);
+ADD_ACKNOWLEDGER (Spacing_engraver, rhythmic_grob);
ADD_TRANSLATOR (Spacing_engraver,
"make a SpacingSpanner and do "
max_idx = i;
max_count = counts[i];
}
-
- // printf ("duration %d/%d, count %d\n",
- // durations[i].num (), durations[i].den (), counts[i]);
}
SCM bsd = me->get_property ("base-shortest-duration");
ga = unsmob_grob_array (scm_ga);
}
- p->rank_
- = ga->size ()
- ? Paper_column::get_rank (ga->array ().back ()) + 1
- : 0;
+ p->rank_ = ga->size ();
ga->add (p);
Axis_group_interface::add_element (this, p);
Moment barleft = (measure_length () - measure_position (context ()));
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->add_moment_to_process (now + barleft);
+ if (barleft > Moment (0))
+ {
+ Moment nextmom = now + barleft;
+ nextmom.grace_part_ = Rational (0);
+ global->add_moment_to_process (nextmom);
+ }
}
}
\consists "Script_engraver"
\consists "Script_column_engraver"
\consists "Rhythmic_column_engraver"
+ \consists "Note_spacing_engraver"
\consists "Phrasing_slur_engraver"
\consists "Cluster_spanner_engraver"
\consists "Slur_engraver"
\consists "Chord_name_engraver"
\consists "Skip_event_swallow_translator"
\consists "Hara_kiri_engraver"
-
+% \consists "Note_spacing_engraver"
voltaOnThisStaff = ##f
\override VerticalAxisGroup #'minimum-Y-extent = #'(0 . 2.5)
\override SeparatingGroupSpanner #'padding = #0.8
(span-dynamic-event . (decrescendo-event crescendo-event))
(pedal-event . (sostenuto-event sustain-event una-corda-event))
(rhythmic-event . (lyric-event melodic-event multi-measure-rest-event
+ percent-event
rest-event skip-event bass-figure-event))
(melodic-event . (cluster-note-event note-event))
(() . (Announcement))
(ly:add-interface
'rhythmic-grob-interface
- "Any object with a rhythmic basis. Used to determine which grobs
-are interesting enough to maintain a hara-kiri staff."
+ "Any object with a duration. Used to determine which grobs are
+interesting enough to maintain a hara-kiri staff."
'())
. (
(Y-extent . ,ly:cluster-beacon::height)
(meta . ((class . Item)
- (interfaces . (cluster-beacon-interface))))))
+ (interfaces . (rhythmic-grob-interface
+ cluster-beacon-interface))))))
(ClusterSpanner
. (
(thickness . 0.48)
(slope . 1.7)
(meta . ((class . Item)
- (interfaces . (percent-repeat-item-interface))))))
+ (interfaces . (rhythmic-grob-interface
+ percent-repeat-item-interface))))))
(RepeatTie
. (
(PercentEvent
. (
(description . "Used internally to signal percent repeats.")
- (types . (general-music event percent-event))
+ (types . (general-music event percent-event rhythmic-event))
))
(PesOrFlexaEvent
import lilylib as ly
global _;_=ly._
-from convertrules import *
+import convertrules
lilypond_version_re_str = '\\\\version *\"([0-9.]+)"'
lilypond_version_re = re.compile (lilypond_version_re_str)
def get_conversions (from_version, to_version):
def is_applicable (v, f = from_version, t = to_version):
return version_cmp (v[0], f) > 0 and version_cmp (v[0], t) <= 0
- return filter (is_applicable, conversions)
+ return filter (is_applicable, convertrules.conversions)
def latest_version ():
- return conversions[-1][0]
+ return convertrules.conversions[-1][0]
def show_rules (file, from_version, to_version):
- for x in conversions:
+ for x in convertrules.conversions:
if (not from_version or x[0] > from_version) \
and (not to_version or x[0] <= to_version):
file.write ('%s: %s\n' % (tup_to_str (x[0]), x[2]))
string."""
conv_list = get_conversions (from_version, to_version)
- if error_file:
- error_file.write (_ ("Applying conversion: "))
+ if convertrules.error_file:
+ convertrules.error_file.write (_ ("Applying conversion: "))
last_conversion = ()
try:
for x in conv_list:
- error_file.write (tup_to_str (x[0]))
+ convertrules.error_file.write (tup_to_str (x[0]))
if x != conv_list[-1]:
- error_file.write (', ')
+ convertrules.error_file.write (', ')
str = x[1] (str)
last_conversion = x[0]
- except FatalConversionError:
- error_file.write (_ ("error while converting"))
- error_file.write ('\n')
- error_file.write (_ ("Aborting"))
- error_file.write ('\n')
-
-
+ except convertrules.FatalConversionError:
+ convertrules.error_file.write ('\n'
+ + _ ("Error while converting")
+ + '\n'
+ + _ ("Stopping at last succesful rule")
+ + '\n')
return (last_conversion, str)
elif not global_options.skip_version_add:
result = newversion + '\n' + result
- error_file.write ('\n')
+ convertrules.error_file.write ('\n')
if global_options.edit:
try: