2005-03-02 Jan Nieuwenhuizen <janneke@gnu.org>
- * configure.in (MAKEINFO): Require 4.7 (ZbynÄ\9bk Burget).
+ * configure.in (MAKEINFO): Require 4.7 (ZbynÃ\84Â\9bk Burget).
+2005-03-04 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * VERSION: release 2.4.5
+
+ * input/regression/tie-arpeggio.ly: new file. Backport.
+
+2005-02-20 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * scm/define-context-properties.scm
+ (all-user-translation-properties): add tieWaitForNote
+
+ * scm/define-grobs.scm (all-grob-descriptions): add
+ Tie_column::before_line_breaking
+
+ * lily/tie.cc (get_column_rank): new function
+
+ * lily/tie-column.cc (before_line_breaking): new function.
+ (werner_directions): take into account ties that start on
+ different columns.
+
+ * lily/score-engraver.cc (set_columns): move add_column() so we
+ have column rank available.
+
+ * lily/tie.cc (get_column_rank): new function.
+
2005-02-28 Jan Nieuwenhuizen <janneke@gnu.org>
* scm/define-grob-properties.scm (all-user-grob-properties):
(The Lyrics context): Corrected link to the SATB example.
+2004-12-24 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * VERSION (PACKAGE_NAME): release 2.4.4
+
+2004-12-24 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * stepmake/stepmake/metafont-rules.make ($(outdir)/%.pfb): update
+ to mftrace 1.1
+
2004-12-26 Jan Nieuwenhuizen <janneke@gnu.org>
* Documentation/user/changing-defaults.itely: Fix internalsrefs
* tex/lily-pdf-defs.tex, tex/lily-ps-defs.tex
(\lilypondexperimentalfeatures): Removed.
-2004-10-20 Jürgen Reuter <reuter@ipd.uka.de>
+2004-10-20 JÃ\83¼rgen Reuter <reuter@ipd.uka.de>
* Documentation/user/notation.itely: fixed 2 typos
mechanism automatically splits long notes, and ties them across bar
lines.
+Ties are sometimes used to write out arpeggios. In this case, two tied
+notes need not be consecutive. This can be achieved by setting the
+@code{tieWaitForNote} property to true. For example,
+
+@lilypond[fragment,verbatim,relative=1,raggedright]
+\set tieWaitForNote = ##t
+\grace { c16[~ e~ g]~ } <c, e g>4
+@end lilypond
+
+
@refcommands
@subsection Arpeggio
@cindex Arpeggio
-@cindex broken arpeggio
+@cindex broken chord
@cindex @code{\arpeggio}
-You can specify an arpeggio sign on a chord by attaching an
-@code{\arpeggio} to a chord
+You can specify an arpeggio sign (also known as broken chord) on a
+chord by attaching an @code{\arpeggio} to a chord
@lilypond[quote,raggedright,fragment,relative=1,verbatim]
@seealso
+Notation manual: @ref{Ties}, for writing out arpeggios.
+
Program reference: @internalsref{ArpeggioEvent},
@internalsref{Arpeggio}.
+
+
@refbugs
It is not possible to mix connected arpeggios and unconnected
PACKAGE_NAME=LilyPond
MAJOR_VERSION=2
MINOR_VERSION=4
-PATCH_LEVEL=3
+PATCH_LEVEL=5
MY_PATCH_LEVEL=
# perl for help2man.
STEPMAKE_PERL(OPTIONAL)
# mftrace for generating pfa's, pfb's
-STEPMAKE_PROGS(MFTRACE, mftrace, OPTIONAL, 1.0.27)
+STEPMAKE_PROGS(MFTRACE, mftrace, OPTIONAL, 1.1.1)
# new makeinfo for multi-page website docs
STEPMAKE_PROGS(MAKEINFO, makeinfo, REQUIRED, 4.7)
}
-\version "2.5.12"
+\version "2.4.5"
\paper { raggedright = ##t }
\relative {
static bool has_interface (Grob*);
static void add_tie (Grob*me,Grob*);
DECLARE_SCHEME_CALLBACK (after_line_breaking, (SCM));
+ DECLARE_SCHEME_CALLBACK (before_line_breaking, (SCM));
static void set_directions (Grob*me);
- static void old_directions (Grob*me);
static void werner_directions (Grob*me);
};
static void set_direction (Grob*);
static Grob * head (Grob*,Direction) ;
static Real get_position (Grob*) ;
- DECLARE_SCHEME_CALLBACK (print, (SCM ));
+ static int get_column_rank (Grob*, Direction);
static Direction get_default_dir (Grob*) ;
static SCM get_control_points (SCM);
DECLARE_SCHEME_CALLBACK (set_spacing_rods, (SCM ));
+ DECLARE_SCHEME_CALLBACK (print, (SCM ));
};
#endif // TIE_HH
pscore_->typeset_line (new System (props));
- make_columns ();
system_ = pscore_->system_;
+ make_columns ();
system_->set_bound (LEFT, command_column_);
command_column_->set_property ("breakable", SCM_BOOL_T);
progress_indication ("[" + to_string (breaks_) + "]");
}
-
- system_->add_column (command_column_);
- system_->add_column (musical_column_);
command_column_ = 0;
musical_column_ = 0;
{
context ()->set_property ("currentMusicalColumn", new_musical->self_scm ());
}
+
+ system_->add_column (command_column_);
+ system_->add_column (musical_column_);
}
Music_output*
*/
+#include "paper-column.hh"
#include "spanner.hh"
#include "tie-column.hh"
#include "group-interface.hh"
#include "rhythmic-head.hh"
-
-
-
-
/*
tie dir depends on what Tie_column does.
*/
-/*
- TODO: this doesn't follow standard pattern. Regularize.
- */
+
+
void
-Tie_column::add_tie (Grob*me,Grob *s)
+Tie_column::add_tie (Grob*me, Grob *tie)
{
- if (s->get_parent (Y_AXIS)
- && Tie_column::has_interface (s->get_parent (Y_AXIS)))
+ if (tie->get_parent (Y_AXIS)
+ && Tie_column::has_interface (tie->get_parent (Y_AXIS)))
return ;
-
- if (! Pointer_group_interface::count (me, "ties"))
+
+
+ if (!Pointer_group_interface::count (me, "ties"))
{
- dynamic_cast<Spanner*> (me)->set_bound (LEFT, Tie::head (s,LEFT));
- dynamic_cast<Spanner*> (me)->set_bound (RIGHT, Tie::head (s,RIGHT));
+ dynamic_cast<Spanner*> (me)->set_bound (LEFT, Tie::head (tie, LEFT));
+ dynamic_cast<Spanner*> (me)->set_bound (RIGHT, Tie::head (tie, RIGHT));
}
- s->set_parent (me, Y_AXIS);
- Pointer_group_interface::add_grob (me, ly_symbol2scm ("ties"), s);
- s->add_dependency (me);
+
+
+ tie->set_parent (me, Y_AXIS);
+ Pointer_group_interface::add_grob (me, ly_symbol2scm ("ties"), tie);
+ tie->add_dependency (me);
}
+
void
Tie_column::set_directions (Grob*me)
{
return sign (Tie::get_position (s1) - Tie::get_position (s2));
}
-/*
- See [Ross p. 138].
-
-
- In normal chord cases, the outer ties point outwards, and the
- direction of the rest is determined by their staff position.
-
- Ross forgets about the tie that is *on* the middle staff line. We
- assume it goes UP. (TODO: make me settable) */
-void
-Tie_column::old_directions (Grob*me)
-{
- Link_array<Grob> ties =
- Pointer_group_interface__extract_grobs (me, (Grob*)0, "ties");
-
- for (int i = ties.size (); i--;)
- if (get_grob_direction (ties[i]))
- ties.del (i);
- if (!ties.size ())
- return ;
-
- Direction d = get_grob_direction (me);
- if (d)
- {
- for (int i = ties.size (); i--;)
- {
- Grob * t = ties[i];
- set_grob_direction (t, d);
- }
- return;
- }
- if (ties.size () == 1)
- {
- Grob * t = ties[0];
- set_grob_direction (t,Tie::get_default_dir (t));
- return;
- }
+/*
+ Werner:
- ties.sort (tie_compare);
- set_grob_direction (ties[0], DOWN);
- ties.del (0);
+ . The algorithm to choose the direction of the ties doesn't work
+ properly. I suggest the following for applying ties sequentially
+ from top to bottom:
- set_grob_direction (ties.pop (), UP);
- for (int i=ties.size (); i--;)
- {
- Grob * t = ties[i];
- Real p = Tie::get_position (t);
- Direction d = (Direction) sign (p);
- if (!d)
- d = UP;
- set_grob_direction (t, d);
- }
+ + The topmost tie is always `up'.
-}
-
-/*
+ + If there is a vertical gap to the last note above larger than
+ or equal to a fifth (or sixth?), the tie is `up', otherwise it
+ is `down'.
-% . The algorithm to choose the direction of the ties doesn't work
-% properly. I suggest the following for applying ties sequentially
-% from top to bottom:
-%
-% + The topmost tie is always `up'.
-%
-% + If there is a vertical gap to the last note above larger than
-% or equal to a fifth (or sixth?), the tie is `up', otherwise it
-% is `down'.
-%
-% + The bottommost tie is always `down'.
-
- */
+ + The bottommost tie is always `down'.
+
+*/
void
Tie_column::werner_directions (Grob *me)
{
Real last_down_pos = 10000;
if (!get_grob_direction (ties[0]))
set_grob_direction (ties[0], DOWN);
-
+
+ /*
+ Go downward.
+ */
+ Grob *last_tie = 0;
for (int i = ties.size (); i--;)
{
Grob *t = ties[i];
Real p = Tie::get_position (t);
if (!d)
{
- if (last_down_pos - p > 5)
+ if (last_tie
+ && Tie::get_column_rank (t, LEFT)
+ < Tie::get_column_rank (last_tie, LEFT))
+ {
+ d = DOWN;
+ }
+ else if (last_down_pos - p > 5)
{
d = UP;
}
if (d == DOWN)
last_down_pos = p;
+
+ last_tie = t;
}
return ;
return SCM_UNSPECIFIED;
}
-
+/*
+ Extend the spanner over its Tie constituents.
+ */
+MAKE_SCHEME_CALLBACK (Tie_column, before_line_breaking, 1);
+SCM
+Tie_column::before_line_breaking (SCM smob)
+{
+ Spanner *me = dynamic_cast<Spanner*> (unsmob_grob (smob));
+ for (SCM s = me->get_property ("ties"); scm_is_pair (s); s = scm_cdr (s))
+ {
+ Spanner *tie = dynamic_cast<Spanner*> (unsmob_grob (scm_car (s)));
+ Direction dir = LEFT;
+ do
+ {
+ if (dir * Paper_column::get_rank (tie->get_bound (dir)->get_column ())
+ > dir * Paper_column::get_rank (me->get_bound (dir)->get_column ()))
+ {
+ me->set_bound (dir, Tie::head (tie, dir));
+ }
+ }
+ while (flip (&dir) != LEFT);
+ }
+ return SCM_UNSPECIFIED;
+}
ADD_INTERFACE (Tie_column,"tie-column-interface",
"Object that sets directions of multiple ties in a tied chord",
TODO: Remove the dependency on musical info. We should tie on the
basis of position and duration-log of the heads (not of the events).
*/
+
+struct Head_event_tuple
+{
+ Grob *head_;
+ SCM tie_definition_;
+ Music *event_;
+ Head_event_tuple()
+ {
+ }
+ Head_event_tuple(Grob *h, Music *m, SCM def)
+ {
+ head_ = h;
+ event_ = m;
+ tie_definition_ = def;
+ }
+};
+
class Tie_engraver : public Engraver
{
Music *event_;
- Music *last_event_;
Link_array<Grob> now_heads_;
- Link_array<Grob> heads_to_tie_;
+ Array<Head_event_tuple> heads_to_tie_;
Link_array<Grob> ties_;
- SCM tie_start_definition_;
Spanner * tie_column_;
};
+void
+Tie_engraver::derived_mark () const
+{
+ Engraver::derived_mark ();
+ for (int i = 0; i < heads_to_tie_.size(); i++)
+ scm_gc_mark (heads_to_tie_[i].tie_definition_);
+}
Tie_engraver::Tie_engraver ()
{
event_ = 0;
- last_event_ = 0;
tie_column_ = 0;
- tie_start_definition_ = SCM_EOL;
-}
-
-void
-Tie_engraver::derived_mark () const
-{
- scm_gc_mark (tie_start_definition_);
}
now_heads_.push (h);
for (int i = heads_to_tie_.size (); i--;)
{
- Grob *th = heads_to_tie_[i];
+ Grob *th = heads_to_tie_[i].head_;
Music * right_mus = unsmob_music (h->get_property ("cause"));
Music * left_mus = unsmob_music (th->get_property ("cause"));
/*
maybe should check positions too.
- */
+ */
if (right_mus && left_mus
&& ly_c_equal_p (right_mus->get_property ("pitch"),
- left_mus->get_property ("pitch")))
+ left_mus->get_property ("pitch")))
{
- Grob * p = new Spanner (tie_start_definition_);
- announce_grob (p, last_event_->self_scm ());
+ Grob * p = new Spanner (heads_to_tie_[i].tie_definition_);
+ announce_grob (p, heads_to_tie_[i].event_->self_scm ());
+
Tie::set_interface (p); // cannot remove yet!
Tie::set_head (p, LEFT, th);
Tie::set_head (p, RIGHT, h);
ties_.push (p);
+ heads_to_tie_.del (i);
}
}
if (ties_.size () && ! tie_column_)
{
- tie_column_ = make_spanner ("TieColumn", SCM_EOL);
-
- }
+ tie_column_ = make_spanner ("TieColumn", ties_[0]->self_scm ());
+ }
if (tie_column_)
for (int i = ties_.size (); i--;)
Tie_engraver::start_translation_timestep ()
{
context ()->set_property ("tieMelismaBusy",
- ly_bool2scm (heads_to_tie_.size ()));
+ ly_bool2scm (heads_to_tie_.size ()));
}
{
if (ties_.size ())
{
- heads_to_tie_.clear ();
+ if (!to_boolean (get_property ("tieWaitForNote")))
+ {
+ heads_to_tie_.clear ();
+ }
for (int i=0; i< ties_.size (); i++)
{
typeset_tie (ties_[i]);
}
ties_.clear ();
- last_event_ = 0;
tie_column_ =0;
}
if (event_)
{
- tie_start_definition_ = updated_grob_properties (context (), ly_symbol2scm ("Tie"));
- heads_to_tie_ = now_heads_;
- last_event_ = event_;
+ SCM start_definition
+ = updated_grob_properties (context (), ly_symbol2scm ("Tie"));
+
+ if (!to_boolean (get_property ("tieWaitForNote")))
+ heads_to_tie_.clear();
+
+ for (int i = 0; i < now_heads_.size(); i++)
+ {
+ heads_to_tie_.push (Head_event_tuple (now_heads_[i], event_,
+ start_definition
+ ));
+ }
+
}
event_ = 0;
now_heads_.clear ();
return 0;
}
+int
+Tie::get_column_rank (Grob *me, Direction d)
+{
+ Spanner *span = dynamic_cast<Spanner*> (me);
+ Grob * h = head (me, d);
+ if (!h)
+ h = span->get_bound (d);
+
+ Grob *col = dynamic_cast<Item*> (h)->get_column ();
+ return Paper_column::get_rank (col);
+}
+
Real
Tie::get_position (Grob*me)
{
$(foreach i, $@, touch $i && ) true
$(outdir)/%.pfa: $(outdir)/%.bla
- $(MFTRACE) -I $(outdir)/ --pfa --simplify --keep-trying $(notdir $(basename $@)) && mv $(notdir $@) $(outdir)/
+ $(MFTRACE) -I $(outdir)/ --formats=pfa --simplify --keep-trying $(notdir $(basename $@)) && mv $(notdir $@) $(outdir)/
$(outdir)/%.enc.in: %.enc
cp $< $@
takes a string number, a list of string tunings and Pitch object. It
returns the text as a string.")
+ (tieWaitForNote ,boolean? "If true, tied notes do not have to follow each other directly.
+This can be used for writing out arpeggios")
(timeSignatureFraction ,number-pair?
"pair of numbers, signifying the time
signature. For example @code{#'(4 . 4)} is a 4/4 time signature.")
(TieColumn
. (
(after-line-breaking-callback . ,Tie_column::after_line_breaking)
+ (before-line-breaking-callback . ,Tie_column::before_line_breaking)
(X-extent-callback . #f)
(Y-extent-callback . #f)
(meta . ((interfaces . (tie-column-interface spanner-interface))))
$(outdir)/%.pfa: %.mf
- $(MFTRACE) $(MFTRACE_FLAGS) -I $(outdir)/ --pfa --simplify $(basename $(@F))
+ $(MFTRACE) $(MFTRACE_FLAGS) -I $(outdir)/ --formats=pfa --simplify $(basename $(@F))
mv $(basename $(@F)).pfa $(outdir)
$(outdir)/%.pfb: %.mf
- $(MFTRACE) $(MFTRACE_FLAGS) -I $(outdir)/ --pfa --pfb --simplify $(basename $(@F))
+ $(MFTRACE) $(MFTRACE_FLAGS) -I $(outdir)/ --formats=pfa,pfb --simplify $(basename $(@F))
-mv $(basename $(@F)).pfa $(outdir)
mv $(basename $(@F)).pfb $(outdir)