From: fred Date: Wed, 27 Mar 2002 02:04:49 +0000 (+0000) Subject: lilypond-1.5.27 X-Git-Tag: release/1.5.59~369 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=4f39e6816d915c6b4059a9cc981b8050c4784440;p=lilypond.git lilypond-1.5.27 --- diff --git a/input/test/staff-size.ly b/input/test/staff-size.ly index 854d6cc4ab..3dbe63ee08 100644 --- a/input/test/staff-size.ly +++ b/input/test/staff-size.ly @@ -1,16 +1,19 @@ \version "1.3.146" \score { \notes \relative c' < \context Voice { - \property Staff.staffSpace = #10 + \context Staff \outputproperty #(make-type-checker 'staff-symbol-interface) + #'staff-space = #(/ 16 20) + \property Staff.fontSize = #-1 \property Voice.fontSize = #-1 - \property Voice . dynamicDirection = \up \stemDown -%\key gis \major + \dynamicUp\stemDown + + %\key gis \major c8 d [e f g a] b c \ff } -\context Staff = VB { \property Voice . dynamicDirection = \down c,,4 \ff c c c } +\context Staff = VB { \dynamicDown c,,4 \ff c c c } > \paper { linewidth = -1. } diff --git a/lily/third-try.cc b/lily/third-try.cc index b66e5f6129..bfc1a34ac8 100644 --- a/lily/third-try.cc +++ b/lily/third-try.cc @@ -6,103 +6,545 @@ (c) 1999--2001 Han-Wen Nienhuys */ +#include "line-of-score.hh" +#include "paper-score.hh" +#include "paper-column.hh" +#include "item.hh" +#include "moment.hh" +#include "note-spacing.hh" +#include "misc.hh" +#include "warn.hh" +/* + paper-column: -#include "paper-column.hh" + right-neighbors = List of spacing-wish grobs that are close to the + current column. + + */ class Third_spacing_spanner { public: - void find_loose_columns () {} - void prune_loose_colunms (Link_array *cols); - void find_loose_columns (Link_array cols); + 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) ; + + static void breakable_column_spacing (Item* l, Item *r); + static void find_loose_columns () {} + static void prune_loose_colunms (Link_array *cols); + static void find_loose_columns (Link_array cols); + static void set_explicit_neighbor_columns (Link_array cols); + static void set_implicit_neighbor_columns (Link_array cols); + static void do_measure (Grob*me,Link_array *cols); + DECLARE_SCHEME_CALLBACK (set_springs, (SCM )); }; +/* + Return whether COL is fixed to its neighbors by some kind of spacing + constraint. +*/ static bool -fixed_neighbor (Grob *col, SCM nm) +loose_column (Grob *l, Grob *c, Grob *r) { - SCM l = col->internal_get_grob_property (nm); + SCM rns = c->get_grob_property ("right-neighbors"); + SCM lns = c->get_grob_property ("left-neighbors"); + + /* + If this column doesn't have a proper neighbor, we should really + make it loose, but spacing it correctly is more than we can + currently can handle. + + (this happens in the following situation: + + | + | clef G + * + + | | || + | | || + O O || + + + 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 border line case. - if (!gh_pair_p (l)) + ) + + */ + if (!gh_pair_p (lns) || !gh_pair_p (rns)) return false; - Item * left = dynamic_cast (unsmob_grob (gh_car (l))); - return abs (Paper_column::rank_i (left->column_l ()) - Paper_column::rank_i (col)) == 1 ; + Item * l_neighbor = dynamic_cast (unsmob_grob (gh_car (lns))); + Item * r_neighbor = dynamic_cast (unsmob_grob (gh_car (rns))); + + if (!l_neighbor || !r_neighbor) + return false; + + l_neighbor = l_neighbor->column_l(); + r_neighbor = r_neighbor->column_l(); + + if (l == l_neighbor && r == r_neighbor) + return false; + + + /* + Only declare loose if the bounds make a little sense. This means + 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)) + && (Paper_column::musical_b (r_neighbor) || Item::breakable_b (r_neighbor))) + { + return true; + } + + + /* + If in doubt: we're not loose; the spacing engine should space for + it, risking suboptimal spacing. + + (Otherwise, we might risk core dumps, and other weird stuff.) + + + */ + return false; } +/* + Remove columns that are not tightly fitting from COLS. In the + removed columns, set 'between-cols to the columns where it is in + between. +*/ void Third_spacing_spanner::prune_loose_colunms (Link_array *cols) { - for (int i=cols->size (); i--; ) - { - - if (Item::breakable_b (cols->elem(i))) - continue; - - if (!fixed_neighbor (cols->elem(i), ly_symbol2scm ("left-neighbors")) - || !fixed_neighbor (cols->elem(i), ly_symbol2scm ("right-neighbors"))) - cols->del (i); - } + Link_array newcols; + + for (int i=0; i < cols->size (); i++) + { + if (Item::breakable_b (cols->elem(i)) || Paper_column::musical_b (cols->elem (i))) + { + newcols.push (cols->elem(i)); + continue; + } + + Grob *c = cols->elem(i); + if (loose_column (cols->elem (i-1), c, cols->elem (i+1))) + { + SCM lns = c->get_grob_property ("left-neighbors"); + lns = gh_pair_p (lns) ? gh_car (lns) : SCM_BOOL_F; + + SCM rns = c->get_grob_property ("right-neighbors"); + rns = gh_pair_p (rns) ? gh_car (rns) : SCM_BOOL_F; + + /* + Either object can be non existent, if the score ends + prematurely. + */ + rns = gh_car (unsmob_grob (rns)->get_grob_property ("right-items")); + c->set_grob_property ("between-cols", gh_cons (lns, + rns)); + } + else + { + newcols.push (c); + } + } + + *cols = newcols; } +/* + Set neighboring columns determined by the spacing-wishes grob property. +*/ void -Third_spacing_spanner::find_loose_columns (Link_array cols) +Third_spacing_spanner::set_explicit_neighbor_columns (Link_array cols) { - for (int i=0; i< cols.size(); i++) + for (int i=0; i < cols.size(); i++) { SCM right_neighbors = SCM_EOL; int min_rank = 100000; // inf. - - for (SCM s = cols[i]-> get_grob_property ("spacing-wishes"); - gh_pair_p (s); s = gh_cdr (s)) - { - Grob * wish = unsmob_grob (gh_car (s)); - Grob * left = unsmob_grob (wish->get_grob_property ("left-item")); - Grob * right = unsmob_grob (wish->get_grob_property ("right-item")); - Item * li = dynamic_cast (left); - Item * ri = dynamic_cast (right); - assert (li->column_l () == cols[i]); + SCM wishes= cols[i]-> get_grob_property ("spacing-wishes"); + for (SCM s =wishes; gh_pair_p (s); s = gh_cdr (s)) + { + Item * wish = dynamic_cast (unsmob_grob (gh_car (s))); + + Item * lc = wish->column_l (); + Grob * right = unsmob_grob (wish->get_grob_property ("right-column")); + + if (!right) + continue; - Item * rc = ri->column_l (); - Item * lc = li->column_l (); - int newrank = Paper_column::rank_i (lc); + Item * rc = dynamic_cast (right); - SCM neighbors = rc->get_grob_property ("left-neighbors"); - Item * left_neighbor = gh_pair_p (neighbors) - ? dynamic_cast (unsmob_grob (gh_car (neighbors))) : 0; + int right_rank = Paper_column::rank_i (rc); + int left_rank = Paper_column::rank_i (lc); - left_neighbor = left_neighbor->column_l (); - if (left_neighbor) + /* + update the left column. + */ + if (right_rank <= min_rank) { - int oldrank = Paper_column::rank_i (left_neighbor->column_l ()); + if (right_rank < min_rank) + right_neighbors =SCM_EOL; + + min_rank = right_rank; + right_neighbors = gh_cons (wish->self_scm (), right_neighbors); + } - if (newrank > oldrank) - { - neighbors= gh_cons (wish->self_scm (), SCM_EOL); - } - else if (newrank == oldrank) - { - neighbors = gh_cons (wish->self_scm (), neighbors); - } + /* + update the right column of the wish. + */ + int maxrank = 0; + SCM left_neighs = rc->get_grob_property ("left-neighbors"); + if (gh_pair_p (left_neighs) + && unsmob_grob (gh_car (left_neighs))) + { + Item * it = dynamic_cast (unsmob_grob (gh_car (left_neighs))); + maxrank = Paper_column::rank_i (it->column_l()); } - if (newrank < min_rank) + if (left_rank >= maxrank) { - right_neighbors = gh_cons (wish->self_scm(), SCM_EOL); - min_rank = newrank; + if (left_rank > maxrank) + left_neighs = SCM_EOL; + + left_neighs = gh_cons (wish->self_scm (), left_neighs); + rc->set_grob_property ("left-neighbors", right_neighbors); } - else if (newrank == min_rank) + } + + if (gh_pair_p (right_neighbors)) + { + cols[i]->set_grob_property ("right-neighbors", right_neighbors); + } + } +} + +/* + Set neighboring columns that have no left/right-neighbor set + yet. Only do breakable non-musical columns, and musical columns. +*/ +void +Third_spacing_spanner::set_implicit_neighbor_columns (Link_array cols) +{ + for (int i = 0; i < cols.size (); i++) + { + Item * it = dynamic_cast(cols[i]); + if (!Item::breakable_b (it) && !Paper_column::musical_b (it)) + continue; + + // it->breakable || it->musical + SCM ln = cols[i] ->get_grob_property ("left-neighbors"); + if (!gh_pair_p (ln) && i ) + { + cols[i]->set_grob_property ("left-neighbors", cols[i-1]->self_scm()); + } + + SCM rn = cols[i] ->get_grob_property ("right-neighbors"); + if (!gh_pair_p (rn) && i < cols.size () - 1) + { + cols[i]->set_grob_property ("right-neighbors", cols[i + 1]->self_scm()); + } + } +} + + +MAKE_SCHEME_CALLBACK (Third_spacing_spanner, set_springs,1); +SCM +Third_spacing_spanner::set_springs (SCM smob) +{ + Grob *me = unsmob_grob (smob); + + Link_array all (me->pscore_l_->line_l_->column_l_arr ()) ; + + set_explicit_neighbor_columns (all); + prune_loose_colunms (&all); + set_implicit_neighbor_columns (all); + + int j = 0; + for (int i = 1; i < all.size (); i++) + { + Grob *sc = all[i]; + if (Item::breakable_b (sc)) + { + Link_array measure (all.slice (j, i+1)); + do_measure (me, &measure); + j = i; + } + } + + return SCM_UNSPECIFIED; +} + + +void +Third_spacing_spanner::do_measure (Grob*me, Link_array *cols) +{ + Moment shortest_in_measure; + + /* + space as if this duration is present. + */ + Moment base_shortest_duration = *unsmob_moment (me->get_grob_property ("maximum-duration-for-spacing")); + shortest_in_measure.set_infinite (1); + + for (int i =0 ; i < cols->size (); i++) + { + if (Paper_column::musical_b (cols->elem (i))) + { + Moment *when = unsmob_moment (cols->elem (i)->get_grob_property ("when")); + + /* + ignore grace notes for shortest notes. + */ + if (when && when->grace_part_) + continue; + + SCM st = cols->elem (i)->get_grob_property ("shortest-starter-duration"); + Moment this_shortest = *unsmob_moment (st); + shortest_in_measure = shortest_in_measure springs; + + for (int i= 0; i < cols->size () - 1; i++) + { + Item * l = dynamic_cast (cols->elem (i)); + Item * r = dynamic_cast (cols->elem (i+1)); + + Paper_column * lc = dynamic_cast (l); + Paper_column * rc = dynamic_cast (r); + + if (!Paper_column::musical_b (l)) + { + breakable_column_spacing (l, r); + + /* + + The case that the right part is broken as well is rather + rare, but it is possible, eg. with a single empty measure, + or if one staff finishes a tad earlier than the rest. + + */ + Item *lb = l->find_prebroken_piece (RIGHT); + Item *rb = r->find_prebroken_piece (LEFT); + + if (lb) + breakable_column_spacing (lb,r); + + if (rb) + breakable_column_spacing (l, rb); + if (lb && rb) + breakable_column_spacing (lb, rb); + + continue ; + } + + Real note_space = note_spacing (me,lc, rc, shortest_in_measure get_grob_property ("arithmetic-multiplier")); + + SCM seq = lc->get_grob_property ("right-neighbors"); + + Moment dt = Paper_column::when_mom (r) - Paper_column::when_mom (l); + + /* + 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; + if (shortest_in_measure <= dt) + { + /* + currently SPACING-SEQUENCE is set in + Separating_group_spanner::find_musical_sequences (), which + works neatly for one-voice-per staff, however, + + it can't find out the actual duration of the notes on a + staff, so when putting tuplets and normal patterns it gets + confused, (ie. believes that < { c8 c8 } { d8 d8 d8 }*2/3 + > contains 1/12 notes. ). + + here we kludge, by checking if the distance we're spacing + for is less than the shortest note. + + TODO: + + Move SPACING-SEQUENCE detection into a voice + level-engraver --or-- make sure that every column has + access to the note head. + + */ + for (SCM s = seq; gh_pair_p (s); s = ly_cdr (s)) { - right_neighbors = gh_cons (wish->self_scm (), right_neighbors); + Grob * wish = unsmob_grob (gh_car (s)); + + // TODO; configgable. + if (Note_spacing::has_interface (wish)) + { + hinterfleisch += -headwid + Note_spacing::get_spacing (wish); + } + + // should move into Note_spacing + // hinterfleisch += stem_dir_correction (me, l, r); } + + // ? why. + if (gh_pair_p (seq)) + stretch_distance -= 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 +Third_spacing_spanner::breakable_column_spacing (Item* l, Item *r) +{ + Spring s; - cols[i]->set_grob_property ("right-neighbors", right_neighbors); + Real break_dist = 0.0; + SCM espace = l->get_grob_property ("extra-space"); + if (gh_pair_p (espace)) + break_dist += gh_scm2double (ly_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 (ly_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 (); +} + + +/** + 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 +Third_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 +Third_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"); + + + 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 = 0.0; + + if (delta_t.main_part_) + { + dist = get_duration_space (me, shortest_playing_len, shortest); + dist *= (double) (delta_t.main_part_ / shortest_playing_len.main_part_); + } + else if (delta_t.grace_part_) + { + dist = get_duration_space (me, shortest, shortest); + + Real grace_fact = 1.0; + SCM gf = me->get_grob_property ("grace-space-factor"); + if (gh_number_p (gf)) + grace_fact = gh_scm2double (gf); + + dist *= grace_fact; + } + +#if 0 + /* + TODO: figure out how to space grace notes. + */ + + dist *= + + grace_fact * (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; } +#endif + + return dist; } + diff --git a/make/lilypond.redhat.spec.in b/make/lilypond.redhat.spec.in index 1489a8cc53..c75f25b10f 100644 --- a/make/lilypond.redhat.spec.in +++ b/make/lilypond.redhat.spec.in @@ -54,7 +54,7 @@ make web-doc top-web rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT/tmp/lilypond-rpm-doc -strip lily/out/lilypond midi2ly/out/midi2ly +strip lily/out/lilypond make prefix="$RPM_BUILD_ROOT%{_prefix}" install %if info=="yes" diff --git a/make/lilypond.suse.spec.in b/make/lilypond.suse.spec.in index 4c3253f95b..1eec5b418b 100644 --- a/make/lilypond.suse.spec.in +++ b/make/lilypond.suse.spec.in @@ -118,7 +118,7 @@ cp tex/titledefs.tex scripts/share/lilypond/tex ## end of hack -strip lily/out/lilypond midi2ly/out/midi2ly +strip lily/out/lilypond make prefix="$RPM_BUILD_ROOT%{_prefix}" install %{INSTALL_DIR} $RPM_BUILD_ROOT/usr/share/texmf/fonts/source/public/lilypond diff --git a/scm/font.scm b/scm/font.scm index d1813de9a1..ffdae61043 100644 --- a/scm/font.scm +++ b/scm/font.scm @@ -205,10 +205,10 @@ (tuplet . ((font-family . roman) (font-shape . italic) (font-relative-size . -1))) (timesig . ((font-family . number) )) - (timesig-symbol . ((font-family . music) (font-relative-size . 0))) + (timesig-symbol . ((font-family . music) )) - (mmrest . ((font-family . number) (font-relative-size . 1))) - (mmrest-symbol . ((font-family . music) (font-relative-size . 0))) + (mmrest . ((font-family . number) )) + (mmrest-symbol . ((font-family . music) )) (mark . ((font-family . number) (font-relative-size . 1))) (script . ((font-family . roman) (font-relative-size . -1))) diff --git a/tex/lilyponddefs.tex b/tex/lilyponddefs.tex index bc30d54039..c47267cead 100644 --- a/tex/lilyponddefs.tex +++ b/tex/lilyponddefs.tex @@ -46,6 +46,8 @@ \fi \ifundefined{lilypondpaperinterscorelinefill} \def\lilypondpaperinterscorelinefill{0} +\else + \def\lilypondpaperinterscorelinefill{1} \fi \def\interscoreline{\vskip\lilypondpaperinterscoreline pt plus %