+2002-03-13 Han-Wen <hanwen@cs.uu.nl>
+
+ * VERSION: 1.5.39 released
+
+ * lily/simple-spacer.cc (add_rod): rods take precedence over
+ infinitely stiff springs. This fixes bugs with arpeggios and bar-lines.
+
+ * lily/arpeggio-engraver.cc (acknowledge_grob): clean up.
+
+ * lily/note-spacing.cc (get_spacing): only insert space for
+ accidentals if necessary.
+
+ * input/regression/spacing-accidental-staffs.ly (texidoc): update example
+
+ * lily/spacing-spanner.cc (musical_column_spacing): new
+ function. Have correct spacing from note to end-of-line as well.
+
+2002-03-12 Jan Nieuwenhuizen <janneke@gnu.org>
+
+ * Documentation/topdocs/INSTALL.texi: Add section for MacOS X.
+
+ * darwin.patch: New file.
+
+ * lily/beam.cc (set_stem_shorten): Revive deceased stem shorten
+ code. Shorten stems by fraction of stems to be shortened.
+
+ * lily/stem.cc (get_default_stem_end_position): Shorten only half
+ of shorten value for boundary cases.
+
+ * scm/grob-description.scm (Stem): Set stem-shorten to (1.0 0.5).
+ (Beam): Set beamed-stem-shorten to (1.0 0.5).
+
+2002-03-11 Jan Nieuwenhuizen <janneke@gnu.org>
+
+ * lily/beam.cc (check_stem_length_f): Try to lenthen more.
+
+ * scm/grob-description.scm (Beam): Add concaveness. Replace
+ Beam::cancel_suspect_slope with Beam::check_concave.
+
+ * lily/beam.cc (check_concave): Calculate concaveness of beam, and
+ set slope to horizontal if concaveness > Beam.concaveness. This
+ handles cases that kludgy cancel_suspect_slope was meant to catch
+ very well.
+ (cancel_suspect_slope): Remove.
+
+2002-03-12 Rune Zedeler <rune@zedeler.dk>
+
+ * lily/beam.cc lily/stem.cc lily/beam-engraver.cc allow for
+ stemLeftBeamCount and stemRightBeamCount to equal 0.
+ Fixes [c8 c4 c8]
+
+2002-03-12 Han-Wen <hanwen@cs.uu.nl>
+
+ * lily/spacing-spanner.cc (breakable_column_spacing): Only do
+ fixed spacing for pref matter, if the next column is musical, and
+ at the same moment.
+
+ * lily/note-spacing.cc (stem_dir_correction): Use correct
+ discretionary for stem-bar spacing.
+
2002-03-11 Han-Wen <hanwen@cs.uu.nl>
+ * VERSION: 1.5.38 released
+
* lily/grob.cc (warning): Use cause tracking to give more
meaningful errors from the backend.
PACKAGE_NAME=LilyPond
MAJOR_VERSION=1
MINOR_VERSION=5
-PATCH_LEVEL=38
+PATCH_LEVEL=39
MY_PATCH_LEVEL=
# use the above to send patches: MY_PATCH_LEVEL is always empty for a
spacing of the quarter notes here."
}
-\score { \notes \relative c'' < \context Staff = SA { \time 8/4
+\score { \notes \relative c'' < \context Staff = SA { \time 4/4
-c4 c4 cis4 cis4
-cis4 cis4 cis4 cis
+[c8 c8 cis8 cis8]
+[cis8 cis8 cis8 cis]
}
- { \key d \major cis2 cis2 cis2 cis!2 } >
+ { \key d \major cis4 cis4 cis4 cis!4 } >
\paper { linewidth = -1. }
}
\header {
texidoc = "Accidentals sticking out to the left
-of a note will take a little more space."
+of a note will take a little more space, but only if the spacing is tight."
}
-\score { \notes \relative c'' { c4 c cis4
+\score { \notes \relative c'' {
+ \time 8/4
+ c2 c2 cis2 cis2 |
+ c8 c8 cis8 cis8 cis c c c]
}
\paper { linewidth = -1. }
#include "musical-request.hh"
#include "arpeggio.hh"
#include "stem.hh"
-#include "local-key-item.hh"
#include "rhythmic-head.hh"
#include "side-position-interface.hh"
-#include "staff-symbol-referencer.hh"
+#include "note-column.hh"
class Arpeggio_engraver : public Engraver
{
TRANSLATOR_DECLARATIONS(Arpeggio_engraver);
protected:
virtual void acknowledge_grob (Grob_info);
- virtual void create_grobs ();
+ virtual void process_music ();
+
virtual void stop_translation_timestep ();
virtual bool try_music (Music *);
private:
Item* arpeggio_;
Arpeggio_req *arpeggio_req_;
- Link_array <Grob> stems_;
- Link_array<Grob> supports_;
};
Arpeggio_engraver::Arpeggio_engraver ()
void
Arpeggio_engraver::acknowledge_grob (Grob_info info)
{
- if (arpeggio_req_)
+ if (arpeggio_)
{
if (Stem::has_interface (info.grob_l_))
{
- stems_.push (info.grob_l_);
+ if (!arpeggio_->get_parent (Y_AXIS))
+ arpeggio_->set_parent (info.grob_l_, Y_AXIS);
+
+ Pointer_group_interface::add_grob (arpeggio_, ly_symbol2scm ("stems"), info.grob_l_);
}
/*
*/
else if (Rhythmic_head::has_interface (info.grob_l_))
{
- supports_.push (info.grob_l_);
+ Side_position_interface::add_support (arpeggio_, info.grob_l_);
+ }
+ else if (Note_column::has_interface (info.grob_l_ ))
+ {
+ info.grob_l_->set_grob_property ("arpeggio", arpeggio_->self_scm ());
}
}
}
void
-Arpeggio_engraver::create_grobs ()
+Arpeggio_engraver::process_music ()
{
- if (!arpeggio_ && !stems_.empty ())
+ if (arpeggio_req_)
{
arpeggio_ = new Item (get_property ("Arpeggio"));
- arpeggio_->set_parent (stems_[0], Y_AXIS);
-
- for (int i = 0; i < stems_.size (); i++)
- {
- Pointer_group_interface::add_grob (arpeggio_, ly_symbol2scm ("stems"), stems_[i]);
- }
- for (int i = 0; i < supports_.size (); i++)
- {
- Side_position_interface::add_support (arpeggio_, supports_[i]);
- }
announce_grob(arpeggio_, arpeggio_req_->self_scm());
}
}
arpeggio_ = 0;
}
arpeggio_req_ = 0;
- stems_.clear ();
- supports_.clear ();
}
ENTER_DESCRIPTION(Arpeggio_engraver,
/* descr */ "Generate an Arpeggio from a Arpeggio_req",
/* creats*/ "Arpeggio",
-/* acks */ "stem-interface rhythmic-head-interface",
+/* acks */ "stem-interface rhythmic-head-interface note-column-interface",
/* reads */ "",
/* write */ "");
public:
static bool has_interface (Grob*);
- static Real get_spacing (Grob *me);
- static Real stem_dir_correction (Grob *me);
+ static void get_spacing (Grob *me, Item* , Real, Real, Real*, Real*);
+ static Real stem_dir_correction (Grob *me, Item * next_col);
static Item * right_column (Grob*);
static Item * left_column (Grob*);
};
return g && g->has_interface (ly_symbol2scm ("note-spacing-interface"));
}
-Real
-Note_spacing::get_spacing (Grob *me)
+void
+Note_spacing::get_spacing (Grob *me, Item* right_col,
+ Real base_space, Real increment, Real *space, Real *fixed)
{
+
Drul_array<SCM> props(me->get_grob_property ("left-items"),
me->get_grob_property ("right-items"));
Direction d = LEFT;
+ Direction col_dir = right_col->break_status_dir ();
Drul_array<Interval> extents;
do
{
for (SCM s = props[d]; gh_pair_p (s); s = gh_cdr (s))
{
Item * it= dynamic_cast<Item*> (unsmob_grob (gh_car(s)));
- extents[d].unite (it->extent (it->column_l (), X_AXIS));
+ if (d == RIGHT && it->break_status_dir () != col_dir)
+ {
+ it = it -> find_prebroken_piece (col_dir);
+ }
+ /*
+ some kind of mismatch, eg. a note column, that is behind a
+ linebreak.
+ */
+ if (!it)
+ continue;
+
+ extents[d].unite (it->extent (it->column_l (), X_AXIS));
if (d == RIGHT)
{
Grob * accs = Note_column::accidentals (it);
}
while (flip (&d) != LEFT);
- /*
+ *fixed = (extents[LEFT][RIGHT] >? increment);
+ *space = (base_space - increment) + *fixed ;
+
+ if (*space - *fixed < 2 * ((- extents[RIGHT][LEFT]) >? 0))
+ {
+ /*
- What's sticking out at the left of the right side has less
- influence.
+ What's sticking out at the left of the right side has less
+ influence. We only take it into account if there is not enough
+ space.
- */
- Real dx= extents[LEFT][RIGHT] - 0.5 * extents[RIGHT][LEFT];
- return dx;
+ this sucks: this criterion is discontinuous; FIXME.
+ */
+ *space += 0.5 * (( -extents[RIGHT][LEFT]) >? 0);
+ }
+
+ *space += stem_dir_correction (me, right_col);
}
Item *
*/
Real
-Note_spacing::stem_dir_correction (Grob*me)
+Note_spacing::stem_dir_correction (Grob*me, Item * rcolumn)
{
Drul_array<Direction> stem_dirs(CENTER,CENTER);
Drul_array<Interval> stem_posns;
{
if (d == RIGHT && Separation_item::has_interface (it))
{
+ if (it->column_l () != rcolumn)
+ {
+ it = it->find_prebroken_piece (rcolumn->break_status_dir ());
+ }
+
Grob *last = Staff_spacing::extremal_break_aligned_grob (it, LEFT, &bar_xextent);
if (last)
goto exit_func;
}
+
if(Stem::invisible_b (stem))
{
correct = false;
programming_error ("Weird minimum distance. Ignoring");
return;
}
-
-
+
Real c = range_stiffness (l,r);
+ if (isinf (c))
+ {
+ /*
+ If a spring is fixed, we have to do something here:
+ we let the rod override the spring.
+ */
+ Real total_dist = 0.;
+ for (int i = l ; i < r; i++)
+ total_dist += springs_[i].ideal_f_;
+
+ if (total_dist < dist)
+ for (int i = l ; i < r; i++)
+ springs_[i].ideal_f_ *= dist/total_dist;
+
+ return;
+ }
+
Real d = range_ideal_len (l,r);
Real block_stretch = dist - d;
void
Spaceable_grob::add_spring (Grob*me, Grob * p, Real d, Real strength, bool expand_only)
{
+ if (d < 0.0 || strength <= 0.0)
+ {
+ programming_error ("Adding reverse spring!");
+ }
+
#ifndef NDEBUG
SCM mins = me->get_grob_property ("ideal-distances");
for (SCM s = mins; gh_pair_p (s); s = ly_cdr (s))
a little baroque, but it might come in handy later on?
*/
-
class Spacing_spanner
{
public:
static Rational find_shortest (Link_array<Grob> const &);
static void breakable_column_spacing (Item* l, Item *r);
static void find_loose_columns () {}
- static void prune_loose_colunms (Link_array<Grob> *cols);
+ static void prune_loose_colunms (Grob*,Link_array<Grob> *cols, Rational);
static void find_loose_columns (Link_array<Grob> cols);
static void set_explicit_neighbor_columns (Link_array<Grob> cols);
static void set_implicit_neighbor_columns (Link_array<Grob> cols);
static void do_measure (Rational, Grob*me,Link_array<Grob> *cols);
+ static void musical_column_spacing (Grob*,Item*,Item*, Real, Rational);
DECLARE_SCHEME_CALLBACK (set_springs, (SCM ));
};
the column containing the clef is really loose, and should be
attached right to the first column, but that is a lot of work for
- such a borderline case.
-
- )
+ such a borderline case.)
*/
if (!gh_pair_p (lns) || !gh_pair_p (rns))
some cases (two isolated, consecutive clef changes) won't be
nicely folded, but hey, then don't do that.
*/
- if( (Paper_column::musical_b (l_neighbor) || Item::breakable_b (l_neighbor))
+ if ((Paper_column::musical_b (l_neighbor) || Item::breakable_b (l_neighbor))
&& (Paper_column::musical_b (r_neighbor) || Item::breakable_b (r_neighbor)))
{
return true;
between.
*/
void
-Spacing_spanner::prune_loose_colunms (Link_array<Grob> *cols)
+Spacing_spanner::prune_loose_colunms (Grob*me,Link_array<Grob> *cols, Rational shortest)
{
Link_array<Grob> newcols;
-
+ Real increment = gh_scm2double (me->get_grob_property ("spacing-increment"));
for (int i=0; i < cols->size (); i++)
{
if (Item::breakable_b (cols->elem(i)) || Paper_column::musical_b (cols->elem (i)))
do
{
dists[d] = 0.0;
- Grob *lc = (d == LEFT) ? next_door[LEFT] : c;
- Grob *rc = d == LEFT ? c : next_door[RIGHT];
+ Item *lc = dynamic_cast<Item*> ((d == LEFT) ? next_door[LEFT] : c);
+ Item *rc = dynamic_cast<Item*> (d == LEFT ? c : next_door[RIGHT]);
for (SCM s = lc->get_grob_property ("spacing-wishes");
gh_pair_p (s); s = gh_cdr (s))
|| Note_spacing::right_column (sp) != rc)
continue;
- dists[d] = dists[d] >? Note_spacing::get_spacing (sp);
+ Real space, fixed;
+ fixed = 0.0;
+ bool expand_only;
+ Real base = note_spacing (me, lc, rc, shortest, &expand_only);
+ Note_spacing::get_spacing (sp, rc, base, increment, &space, &fixed);
+ space -=base;
+
+ dists[d] = dists[d] >? space;
}
}
while (flip (&d) != LEFT);
Link_array<Grob> all (me->pscore_l_->line_l_->column_l_arr ()) ;
set_explicit_neighbor_columns (all);
- prune_loose_colunms (&all);
- set_implicit_neighbor_columns (all);
Rational global_shortest = find_shortest (all);
+ prune_loose_colunms (me, &all, global_shortest);
+ set_implicit_neighbor_columns (all);
+
int j = 0;
for (int i = 1; i < all.size (); i++)
continue ;
}
- bool expand_only = false;
- Real note_space = note_spacing (me, lc, rc, shortest, &expand_only);
-
- Real hinterfleisch = note_space;
-
-
- SCM seq = lc->get_grob_property ("right-neighbors");
- /*
- hinterfleisch = hind-meat = amount of space following a note.
-
-
- We adjust the space following a note only if the next note
- happens after the current note (this is set in the grob
- property SPACING-SEQUENCE. */
- Real stretch_distance = note_space;
+ musical_column_spacing (me, lc, rc, headwid, shortest);
+ if (Item *rb = r->find_prebroken_piece (LEFT))
+ musical_column_spacing (me, lc, rb, headwid, shortest);
+ }
+}
- hinterfleisch = -1.0;
- Real max_factor = 0.0;
- for (SCM s = seq; gh_pair_p (s); s = ly_cdr (s))
- {
- Grob * wish = unsmob_grob (gh_car (s));
+void
+Spacing_spanner::musical_column_spacing (Grob *me, Item * lc, Item *rc, Real increment, Rational shortest)
+{
+ bool expand_only = false;
+ Real base_note_space = note_spacing (me, lc, rc, shortest, &expand_only);
- if (Note_spacing::left_column (wish) != lc
- || Note_spacing::right_column (wish) != rc)
- continue;
+ Real max_note_space = -infinity_f;
+ Real max_fixed_note_space = -infinity_f;
- /*
- This is probably a waste of time in the case of polyphonic
- music. */
- if (Note_spacing::has_interface (wish))
- {
- hinterfleisch = hinterfleisch >?
- ( - headwid +
+ SCM seq = lc->get_grob_property ("right-neighbors");
- (note_space + Note_spacing::get_spacing (wish))
- *gh_scm2double (wish->get_grob_property ("space-factor"))
+ /*
+ We adjust the space following a note only if the next note
+ happens after the current note (this is set in the grob
+ property SPACING-SEQUENCE.
+ */
+ for (SCM s = seq; gh_pair_p (s); s = ly_cdr (s))
+ {
+ Grob * wish = unsmob_grob (gh_car (s));
- + Note_spacing::stem_dir_correction (wish));
- }
- }
+ Item *wish_rcol = Note_spacing::right_column (wish);
+ if (Note_spacing::left_column (wish) != lc
+ || (wish_rcol != rc && wish_rcol != rc->original_l_))
+ continue;
- if (hinterfleisch < 0)
+ /*
+ This is probably a waste of time in the case of polyphonic
+ music. */
+ if (Note_spacing::has_interface (wish))
{
- // maybe should issue a programming error.
- hinterfleisch = note_space;
+ Real space =0.0;
+ Real fixed =0.0;
+
+ Note_spacing::get_spacing (wish, rc, base_note_space, increment, &space, &fixed);
+ max_note_space = max_note_space >? space;
+ max_fixed_note_space = max_fixed_note_space >? fixed;
}
- else
- stretch_distance -= headwid; // why?
- if (max_factor == 0.0)
- max_factor = 1.0;
-
- Spaceable_grob::add_spring (l, r, max_factor * hinterfleisch, 1 / stretch_distance, expand_only);
+ }
- /*
- TODO: we should have a separate routine determining this distance!
- */
- if (Item *rb = r->find_prebroken_piece (LEFT))
- {
- Spaceable_grob::add_spring (l, rb, max_factor * hinterfleisch, 1 / stretch_distance, expand_only);
- }
+ if (max_note_space < 0)
+ {
+ max_note_space = base_note_space;
+ max_fixed_note_space = increment;
}
+ Spaceable_grob::add_spring (lc, rc, max_note_space, 1 / (max_note_space -max_fixed_note_space), expand_only);
}
+
/*
Read hints from L (todo: R) and generate springs.
*/
for (SCM s = l->get_grob_property ("spacing-wishes");
gh_pair_p (s); s = gh_cdr (s))
{
- Grob * spacing_grob = unsmob_grob (gh_car (s));
+ Item * spacing_grob = dynamic_cast<Item*> (unsmob_grob (gh_car (s)));
if (!spacing_grob || !Staff_spacing::has_interface (spacing_grob))
continue;
Real space;
Real fixed_space;
+ /*
+ column for the left one settings should be ok due automatic
+ pointer munging.
+
+ */
+ assert (spacing_grob-> column_l () == l);
+
Staff_spacing::get_spacing_params (spacing_grob,
&space, &fixed_space);
if (space > max_space)
max_fixed = 1.0;
}
+
+ if (l->break_status_dir() == RIGHT
+ && Paper_column::when_mom (l) == Paper_column::when_mom (r))
+ {
+ /* Start of line: this space is not stretchable */
+ max_fixed = max_space;
+ }
+
+ /*
+ Hmm. we do 1/0 in the next thing. Perhaps we should check if this
+ works on all architectures.
+ */
+
Spaceable_grob::add_spring (l, r, max_space, 1/(max_space - max_fixed), false);
}
Item *col =dynamic_cast<Item*> (g)->column_l ();
Real max_corr = 0. >? (- g->extent (col, X_AXIS)[LEFT]);
+
+ /*
+ Duh. If this gets out of hand, we should invent something more generic.
+ */
if (Grob * a = Note_column::accidentals (g))
{
max_corr = max_corr >? (- a->extent (col, X_AXIS)[LEFT]);
}
-
+ if (Grob* a = unsmob_grob (g->get_grob_property ("arpeggio")))
+ {
+ max_corr = max_corr >? (- a->extent (col, X_AXIS)[LEFT]);
+ }
+
/*
Let's decrease the space a little if the problem is not located
after a barline.
*space += next_notes_correction (me, last_grob);
-
- if (dynamic_cast<Item*> (me)-> break_status_dir () == RIGHT)
- {
- /* Start of line: this space is not stretchable */
- *fixed = *space;
- }
-
}
% input feta-bolletjes;
% input feta-banier;
% input feta-eindelijk;
-% input feta-klef;
-% input feta-toevallig;
+ input feta-klef;
+ input feta-toevallig;
% input feta-schrift;
% input feta-haak;
% input feta-timesig;
pickup pencircle scaled 1;
% draw
fill
- new_bulb (z1, 0.4 reduced_ss, 0.35 reduced_ss, 2 stafflinethickness, 1)
+ new_bulb (z1, 0.45 reduced_ss, 0.4 reduced_ss, 2.5 stafflinethickness, 1)
{dir (90)}
.. z2r{right} .. tension 1.0 .. z3r{down} .. {curl 0}
(after-line-breaking-callback . ,Local_key_item::after_line_breaking)
(direction . -1)
(left-padding . 0.2)
- (right-padding . 0.4)
+ (right-padding . 0.5)
(paren-cautionaries . #t)
(font-family . music)
(meta . ,(grob-description accidentals-interface font-interface side-position-interface))
(time-signature . (extra-space . 0.75))
(custos . (minimum-space . 2.0))
(clef . (minimum-space . 1.0))
- (begin-of-note . (extra-space . 1.0))
+ (begin-of-note . (extra-space . 1.3))
))
;;
;; todo: clean this up a bit: the list is getting
;; rather long.
(molecule-callback . ,Beam::brew_molecule)
+;; (concaveness . 0.8)
+ (concaveness . 0.08)
+ (concaveness-no-slope . #t)
+ (concaveness-square . #t)
+ (ideal-lengthen . #t)
(y-dy-callbacks . (,Beam::least_squares
- ,Beam::cancel_suspect_slope
+ ,Beam::check_concave
,Beam::slope_damping
,Beam::quantise_dy
,Beam::user_override
(dir-function . ,beam-dir-majority)
(height-quants . ,default-beam-dy-quants)
(vertical-position-quant-function . ,default-beam-y-quants)
- (beamed-stem-shorten . (0.5))
+ (beamed-stem-shorten . (1.0 0.5))
(outer-stem-length-limit . 0.2)
(slope-limit . 0.2)
(flag-width-function . ,default-beam-flag-width-function)
(shortest-duration-space . 2.0)
(spacing-increment . 1.2)
+
(X-extent-callback . #f)
(Y-extent-callback . #f)
;; a whole staffspace seems a bit drastical: we'll do half.
(lengths . (3.5 3.5 3.5 4.5 5.0))
- (stem-shorten . (0.5))
+ (stem-shorten . (1.0 0.5))
; if stem is on middle line, choose this direction.
(neutral-direction . -1)
(X-offset-callbacks . (,Stem::off_callback))
@ref{spacing-spanner-interface}.")
(grob-property-description 'spacing-increment number? "Add this much space for a doubled duration. Typically, the width of a note head. See also @ref{spacing-spanner-interface}.")
+(grob-property-description 'arpeggio ly-grob? "pointer to arpeggio object.")
(grob-property-description 'arpeggio-direction dir? "If set, put an
arrow on the arpeggio squiggly line.")
(grob-property-description 'attachment pair? "cons of symbols, '(LEFT-TYPE . RIGHT-TYPE), where both types may be alongside-stem, stem, head or loose-end.")