From: fred Date: Wed, 27 Mar 2002 02:04:48 +0000 (+0000) Subject: lilypond-1.5.27 X-Git-Tag: release/1.5.59~370 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=476ff56eddf0d52ceff6c906f6f4125740077180;p=lilypond.git lilypond-1.5.27 --- diff --git a/Documentation/regression-test.tely b/Documentation/regression-test.tely index 0f7791c577..42f5aad17e 100644 --- a/Documentation/regression-test.tely +++ b/Documentation/regression-test.tely @@ -165,6 +165,8 @@ Grace note do weird things with timing. Fragile. @lilypondfile[printfilename]{tie.ly} +@lilypondfile[printfilename]{tie-busy-grobs.ly} + @lilypondfile[printfilename]{tie-chord.ly} @lilypondfile[printfilename]{tie-accidental.ly} diff --git a/input/regression/spacing-accidental-staffs.ly b/input/regression/spacing-accidental-staffs.ly index 58d1ecf1c9..175be7bade 100644 --- a/input/regression/spacing-accidental-staffs.ly +++ b/input/regression/spacing-accidental-staffs.ly @@ -4,13 +4,14 @@ texidoc = "Accidentals in different staffs don't effect the spacing of the quarter notes here." } -\score { \notes \relative c'' < \context Staff = SA { +\score { \notes \relative c'' < \context Staff = SA { \time 8/4 + c4 c4 cis4 cis4 -c4 c4 c4 c +cis4 cis4 cis4 cis } - { \key d \major c2 c2 c2 cis2 } > + { \key d \major cis2 cis2 cis2 cis!2 } > \paper { linewidth = -1. } } diff --git a/input/regression/tie-busy-grobs.ly b/input/regression/tie-busy-grobs.ly new file mode 100644 index 0000000000..719d196f2c --- /dev/null +++ b/input/regression/tie-busy-grobs.ly @@ -0,0 +1,16 @@ +\header { + +texidoc = "Tie engraver uses @code{busyGrobs} to keep track of +note heads. Test if this queue works by throwing many mixed tuplets at it." + +} + +\score +{ +\notes \context Staff \relative c'' + < + \context Voice { \voiceOne \times 2/3 { c'8~ c8~ c8~ c8~ c8~ c8 } } + \context Voice= VII { \voiceThree { b,8 ~ b8 ~ b8 ~ b8 }} + \context Voice = VIII { \voiceTwo \times 2/5 { a,4 ~a4 ~a4~ a4~ a4 }} + > +} diff --git a/lily/accidental-engraver.cc b/lily/accidental-engraver.cc index 015b515e66..0f9b126eb3 100644 --- a/lily/accidental-engraver.cc +++ b/lily/accidental-engraver.cc @@ -54,7 +54,7 @@ public: Link_array arpeggios_; Link_array mel_l_arr_; - Link_array support_l_arr_; + Link_array head_l_arr_; Link_array forced_l_arr_; Link_array tie_l_arr_; @@ -155,19 +155,20 @@ Accidental_engraver::create_grobs () SCM barnum = get_property ("currentBarNumber"); bool extra_natural_b = get_property ("extraNatural")==SCM_BOOL_T; - for (int i=0; i < mel_l_arr_.size (); i++) { - Grob * support_l = support_l_arr_[i]; + Grob * support_l = head_l_arr_[i]; Note_req * note_l = mel_l_arr_[i]; int num = number_accidentals(localsig,note_l,accidentals_l,barnum); int num_caut = number_accidentals(localsig,note_l,cautionaries_l,barnum); bool cautionary = to_boolean (note_l->get_mus_property ("cautionary")); - if (abs(num_caut)>abs(num)) { - num=num_caut; - cautionary=true; - } + if (abs(num_caut)>abs(num)) + { + num=num_caut; + cautionary=true; + } + bool different=num<0; num=abs(num); @@ -200,7 +201,6 @@ Accidental_engraver::create_grobs () key_item_p_ = new Item (get_property ("Accidentals")); Local_key_item::set_interface (key_item_p_); - Staff_symbol_referencer::set_interface (key_item_p_); SCM c0 = get_property ("centralCPosition"); if (gh_number_p (c0)) @@ -215,6 +215,8 @@ Accidental_engraver::create_grobs () num==2 && extra_natural_b, tie_break_reminder); Side_position_interface::add_support (key_item_p_,support_l); + + support_l->set_grob_property ("accidentals", key_item_p_->self_scm ()); } @@ -258,11 +260,9 @@ Accidental_engraver::create_grobs () if (key_item_p_) { /* - Hmm. Which one has to be on the left? - - On which left, code or paper? - - (Arpeggios are engraved left of accidentals, of course.) + We add the accidentals to the support of the arpeggio, so it is put left of the + accidentals. + */ for (int i=0; i < arpeggios_.size (); i++) Side_position_interface::add_support (arpeggios_[i], key_item_p_); @@ -282,8 +282,8 @@ Accidental_engraver::stop_translation_timestep () { if (key_item_p_) { - for (int i=0; i < support_l_arr_.size (); i++) - Side_position_interface::add_support (key_item_p_,support_l_arr_[i]); + for (int i=0; i < head_l_arr_.size (); i++) + Side_position_interface::add_support (key_item_p_,head_l_arr_[i]); typeset_grob (key_item_p_); key_item_p_ =0; @@ -293,7 +293,7 @@ Accidental_engraver::stop_translation_timestep () mel_l_arr_.clear (); arpeggios_.clear (); tie_l_arr_.clear (); - support_l_arr_.clear (); + head_l_arr_.clear (); forced_l_arr_.clear (); } @@ -305,7 +305,7 @@ Accidental_engraver::acknowledge_grob (Grob_info info) if (note_l && Rhythmic_head::has_interface (info.grob_l_)) { mel_l_arr_.push (note_l); - support_l_arr_.push (info.grob_l_); + head_l_arr_.push (info.grob_l_); } else if (Tie::has_interface (info.grob_l_)) { diff --git a/lily/chord-name.cc b/lily/chord-name.cc index 5595759236..2c0e717a89 100644 --- a/lily/chord-name.cc +++ b/lily/chord-name.cc @@ -27,11 +27,6 @@ Chord_name::after_line_breaking (SCM smob) if (to_boolean (s)) { if (Paper_column::rank_i (me->column_l ()) - - /* - hmm, what's my column number in this line? - why doesn't this work? - me->line_l ()->rank_i_ > 2) - */ me->line_l ()->spanned_rank_iv ()[LEFT] > 1) me->suicide (); } diff --git a/lily/completion-note-heads-engraver.cc b/lily/completion-note-heads-engraver.cc index 85609c295a..6d1157560d 100644 --- a/lily/completion-note-heads-engraver.cc +++ b/lily/completion-note-heads-engraver.cc @@ -16,9 +16,22 @@ #include "score-engraver.hh" #include "warn.hh" -/** - make balls and rests +/* + + How does this work? + + When we catch the note, we predict the end of the note. We keep the + requests living until we reach the predicted end-time. + + Every time process_music() is called and there are note requests, we + figure out how long the note to typeset should be. It should be no + longer than what's specified, than what is left to do and it should + not cross barlines. + + We copy the reqs into scratch note reqs, to make sure that we get + all durations exactly right. */ + class Completion_heads_engraver : public Engraver { Link_array note_p_arr_; @@ -72,8 +85,9 @@ Completion_heads_engraver::try_music (Music *m) } else if (dynamic_cast (m)) { - return now_mom () < note_end_mom_; + return note_req_l_arr_.size (); } + return false; } diff --git a/lily/grob-pq-engraver.cc b/lily/grob-pq-engraver.cc new file mode 100644 index 0000000000..fad29ac48d --- /dev/null +++ b/lily/grob-pq-engraver.cc @@ -0,0 +1,159 @@ +/* + grob-pq-engraver.cc -- implement Grob_pq_engraver + + source file of the GNU LilyPond music typesetter + + (c) 2001 Han-Wen Nienhuys +*/ + +#include "translator-group.hh" +#include "engraver.hh" +#include "grob.hh" +#include "warn.hh" + +struct Grob_mom +{ + Grob * grob_ ; + Moment end_; + Grob_mom () {} + Grob_mom (Grob*gr, Moment e) + { + grob_ = gr; + end_ = e; + } +}; + +int compare (Grob_mom const &a, Grob_mom const &b) +{ + return Moment::compare (a.end_, b.end_); +} + +class Grob_pq_engraver: public Engraver +{ +public: + TRANSLATOR_DECLARATIONS(Grob_pq_engraver); + + Array current_grobs_; +protected: + virtual void initialize (); + virtual void acknowledge_grob (Grob_info); + virtual void start_translation_timestep (); + virtual void stop_translation_timestep (); +}; + + +Grob_pq_engraver::Grob_pq_engraver() +{ +} + + +void +Grob_pq_engraver::initialize () +{ + daddy_trans_l_->set_property ("busyGrobs", SCM_EOL); +} + +void +Grob_pq_engraver::acknowledge_grob (Grob_info gi) +{ + Music * m = gi.music_cause (); + + if (m) + { + Moment n = now_mom (); + Moment l = m->length_mom (); + + if (!l.to_bool ()) + return ; + + if (n.grace_part_) + { + l.grace_part_ = l.main_part_; + l.main_part_ = 0; + } + + current_grobs_.push (Grob_mom (gi.grob_l_, n + l)); + } +} + +void +Grob_pq_engraver::stop_translation_timestep () +{ + Moment now = now_mom(); + + current_grobs_.sort (&compare); + + SCM busy = get_property ("busyGrobs"); + while (gh_pair_p (busy) && *unsmob_moment (gh_caar (busy)) == now) + { + busy = gh_cdr (busy); + } + + SCM start = busy; + SCM * current_cell = &start; + + int i = 0; + while (i < current_grobs_.size ()) + { + Moment stop; + stop.set_infinite (1); + + if (gh_pair_p (busy)) + { + SCM h = gh_car (busy); + stop = *unsmob_moment (gh_car (h)); + } + + Moment current_stop = current_grobs_[i].end_; + if (current_stop <= stop) + { + SCM new_entry = gh_cons (current_stop.smobbed_copy(), + current_grobs_[i].grob_->self_scm ()); + + /* + Insert before BUSY. + */ + i ++; + *current_cell = gh_cons (new_entry, busy); + current_cell = SCM_CDRLOC(*current_cell); + } + else + { + /* + if current_stop > stop, then stop != infty, and we + apparently have a next entry */ + busy = gh_cdr (busy); + current_cell = SCM_CDRLOC(*current_cell); + } + } + + current_grobs_.clear (); + daddy_trans_l_->set_property ("busyGrobs", start); +} + +void +Grob_pq_engraver::start_translation_timestep () +{ + Moment now = now_mom(); + + SCM start_busy = get_property ("busyGrobs"); + SCM busy = start_busy; + while (gh_pair_p (busy) && *unsmob_moment (gh_caar (busy)) < now) + { + programming_error ("Skipped something ?!"); + + busy = gh_cdr (busy); + } + + if (start_busy != busy) + daddy_trans_l_->set_property ("busyGrobs", busy); +} + + +ENTER_DESCRIPTION(Grob_pq_engraver, +/* descr */ "Administrate when certain grobs (eg. note heads) stop playing. +", +/* creats*/ "", +/* acks */ "grob-interface", +/* reads */ "busyGrobs", +/* write */ "busyGrobs"); diff --git a/lily/include/grob-info.hh b/lily/include/grob-info.hh index 6d8868214c..578c20730a 100644 --- a/lily/include/grob-info.hh +++ b/lily/include/grob-info.hh @@ -30,7 +30,6 @@ struct Grob_info { GC errors if you don't use music or grobs as a cause. */ SCM cause_; - public: Music * music_cause (); Link_array origin_trans_l_arr (Translator*) const; diff --git a/lily/include/lily-guile.hh b/lily/include/lily-guile.hh index 26c2a8a300..7788833f4b 100644 --- a/lily/include/lily-guile.hh +++ b/lily/include/lily-guile.hh @@ -92,7 +92,15 @@ SCM ly_write2scm (SCM s); SCM ly_deep_copy (SCM); SCM ly_truncate_list (int k, SCM l ); + +#if (__GNUC__ > 2) +/* + todo: should add check for x86 as well + */ #define CACHE_SYMBOLS +#endif + + #ifdef CACHE_SYMBOLS @@ -103,8 +111,6 @@ SCM ly_truncate_list (int k, SCM l ); */ SCM my_gh_symbol2scm (const char* x); -// #warning: CACHE_SYMBOLS - /* Using this trick we cache the value of gh_symbol2scm ("fooo") where "fooo" is a constant string. This is done at the cost of one static diff --git a/lily/include/lyric-combine-music-iterator.hh b/lily/include/lyric-combine-music-iterator.hh index dae14c81dc..8544673a21 100644 --- a/lily/include/lyric-combine-music-iterator.hh +++ b/lily/include/lyric-combine-music-iterator.hh @@ -25,11 +25,12 @@ protected: virtual Moment pending_moment () const; virtual void process (Moment); virtual Music_iterator *try_music_in_children (Music *) const; - + virtual bool ok () const; virtual ~Lyric_combine_music_iterator (); private: + bool get_busy_status ()const ; Music_iterator * music_iter_p_; Music_iterator * lyric_iter_p_; }; diff --git a/lily/include/note-column.hh b/lily/include/note-column.hh index 5f24f7284e..647ac34cb7 100644 --- a/lily/include/note-column.hh +++ b/lily/include/note-column.hh @@ -29,6 +29,7 @@ public: JUNKME. */ + static Grob * accidentals (Grob*me); static Direction dir (Grob*me); static Slice head_positions_interval (Grob* me); static Direction static_dir (Grob*); diff --git a/lily/include/note-spacing.hh b/lily/include/note-spacing.hh index ed92e06519..1905c72e85 100644 --- a/lily/include/note-spacing.hh +++ b/lily/include/note-spacing.hh @@ -15,7 +15,11 @@ source file of the GNU LilyPond music typesetter class Note_spacing { public: - static bool has_interface (Grob*); + static bool has_interface (Grob*); + + static Real get_spacing (Grob *me); + + DECLARE_SCHEME_CALLBACK(before_line_breaking,(SCM)); }; #endif /* NOTE_SPACING_HH */ diff --git a/lily/include/paper-column.hh b/lily/include/paper-column.hh index 507ba6f0fe..4a21edaffc 100644 --- a/lily/include/paper-column.hh +++ b/lily/include/paper-column.hh @@ -19,9 +19,6 @@ class Paper_column : public Item public: VIRTUAL_COPY_CONS (Grob); - /* - Not (yet) in scm, because of messy effects when a column commits suicide. - */ int rank_i_; virtual void do_break_processing (); virtual Paper_column *column_l () const; @@ -30,9 +27,10 @@ public: /// if lines are broken then this column is in #line# Line_of_score *line_l_; - /// which one (left =0) static int rank_i (Grob*); + DECLARE_SCHEME_CALLBACK(brew_molecule, (SCM)); + Paper_column (SCM); static bool musical_b (Grob *); static Moment when_mom (Grob*); diff --git a/lily/line-of-score.cc b/lily/line-of-score.cc index 96f00ce5ba..eaadc08fa5 100644 --- a/lily/line-of-score.cc +++ b/lily/line-of-score.cc @@ -127,13 +127,16 @@ Line_of_score::output_lines () } } + + + /* Find the loose columns in POSNS, and drape them around the columns specified in BETWEEN-COLS. */ void set_loose_columns (Line_of_score* which, Column_x_positions const *posns) { - for (int i = 0; iloose_cols_.size (); i++) + for (int i = 0; i < posns->loose_cols_.size (); i++) { int divide_over = 1; Item *loose = dynamic_cast (posns->loose_cols_[i]); @@ -145,24 +148,30 @@ set_loose_columns (Line_of_score* which, Column_x_positions const *posns) Item * left = 0; Item * right = 0; - while (1) + do { SCM between = loose->get_grob_property ("between-cols"); if (!gh_pair_p (between)) break; - if (!left) + + Item * l=dynamic_cast (unsmob_grob (ly_car (between))); + Item * r=dynamic_cast (unsmob_grob (ly_cdr (between))); + + if (!(l && r)) + break ; + + if (!left && l) { - left = dynamic_cast (unsmob_grob (ly_car (between))); - left = left->column_l (); + left = l->column_l (); } - divide_over ++; - loose = dynamic_cast (unsmob_grob (ly_cdr (between))); - loose = loose->column_l (); - } - right = loose; + divide_over ++; + loose = right = r->column_l (); + } + while (1); + Real rx = right->relative_coordinate (right->get_parent (X_AXIS), X_AXIS); Real lx = left->relative_coordinate (left->get_parent (X_AXIS), X_AXIS); diff --git a/lily/lyric-combine-music-iterator.cc b/lily/lyric-combine-music-iterator.cc index 6052b89ffd..e7e7901e87 100644 --- a/lily/lyric-combine-music-iterator.cc +++ b/lily/lyric-combine-music-iterator.cc @@ -11,6 +11,9 @@ #include "lyric-combine-music-iterator.hh" #include "lyric-combine-music.hh" #include "musical-request.hh" +#include "note-head.hh" +#include "grob.hh" + /* Ugh, why static? @@ -59,6 +62,37 @@ Lyric_combine_music_iterator::construct_children () lyric_iter_p_ = get_iterator_p (m->lyrics_l ()); } +bool +Lyric_combine_music_iterator::get_busy_status () const +{ + /* + We have to use both the request and the busyGrobs queue. The + busyGrobs queue doesn't contain any notes that have started this + instant. */ + if (try_music (busy_req)) + return true; + + Translator_group * tr = music_iter_p_->report_to_l (); + + SCM grobs = tr->get_property ("busyGrobs"); + Moment now = tr->now_mom(); + for (; gh_pair_p (grobs); grobs = gh_cdr (grobs)) + { + SCM grob = gh_cdar (grobs); + Moment end =*unsmob_moment (gh_caar (grobs)); + + + /* + This is slightly ugh: we are now confunding the frontend + (iterators) and the backend (note heads) */ + if (end > now + && Note_head::has_interface (unsmob_grob (grob))) + return true; + } + + return false; +} + void Lyric_combine_music_iterator::process (Moment m) { @@ -68,8 +102,7 @@ Lyric_combine_music_iterator::process (Moment m) music_iter_p_->process (m); - bool busy = try_music (busy_req); - if (busy) + if ( get_busy_status ()) { bool melisma_b = try_music (melisma_playing_req); if (!melisma_b) @@ -101,10 +134,10 @@ Lyric_combine_music_iterator::~Lyric_combine_music_iterator () Lyric_combine_music_iterator::Lyric_combine_music_iterator (Lyric_combine_music_iterator const & src) : Music_iterator (src) { - lyric_iter_p_ = src.lyric_iter_p_ ? src.lyric_iter_p_->clone () : 0; music_iter_p_ = src.music_iter_p_ ? src.music_iter_p_->clone () : 0; } + Music_iterator* Lyric_combine_music_iterator::try_music_in_children (Music *m) const { diff --git a/lily/music-iterator.cc b/lily/music-iterator.cc index f27f2f0d77..4135a6c988 100644 --- a/lily/music-iterator.cc +++ b/lily/music-iterator.cc @@ -161,6 +161,12 @@ Music_iterator::get_iterator_p (Music *m) const return p; } +/* + TODO: rename to prevent confusion between Translator::try_music and + Iterator::try_music + + */ + Music_iterator* Music_iterator::try_music (Music *m) const { diff --git a/lily/note-column.cc b/lily/note-column.cc index 56a29d08a3..95b2cd67ed 100644 --- a/lily/note-column.cc +++ b/lily/note-column.cc @@ -37,7 +37,6 @@ Note_column::shift_compare (Grob *const &p1, Grob *const&p2) void Note_column::set_interface (Grob* me) { - me->set_grob_property ("note-heads", SCM_EOL); me->set_interface (ly_symbol2scm ("note-column-interface")); Axis_group_interface::set_interface (me); @@ -140,3 +139,21 @@ Note_column::has_interface (Grob*me) { return me && me->has_interface (ly_symbol2scm ("note-column-interface")); } + +/* + Return the first Accidentals grob that we find in a note-head. + */ +Grob* +Note_column::accidentals (Grob *me) +{ + SCM heads = me->get_grob_property ("note-heads"); + for (;gh_pair_p (heads); heads =gh_cdr (heads)) + { + Grob * h = unsmob_grob (gh_car (heads)); + Grob *a = h ? unsmob_grob(h->get_grob_property ("accidentals")) : 0; + if (a) + return a; + } + + return 0; +} diff --git a/lily/note-heads-engraver.cc b/lily/note-heads-engraver.cc index 2a9b5e49e4..96938212e4 100644 --- a/lily/note-heads-engraver.cc +++ b/lily/note-heads-engraver.cc @@ -24,7 +24,7 @@ class Note_heads_engraver : public Engraver Link_array dot_p_arr_; Link_array note_req_l_arr_; - Moment note_end_mom_; + public: TRANSLATOR_DECLARATIONS(Note_heads_engraver); @@ -47,14 +47,13 @@ Note_heads_engraver::try_music (Music *m) if (Note_req * n =dynamic_cast (m)) { note_req_l_arr_.push (n); - note_end_mom_ = note_end_mom_ >? now_mom () + m->length_mom (); - return true; } else if (dynamic_cast (m)) { - return now_mom () < note_end_mom_; + return note_req_l_arr_.size (); } + return false; } diff --git a/lily/note-spacing-engraver.cc b/lily/note-spacing-engraver.cc new file mode 100644 index 0000000000..47b11ae5ac --- /dev/null +++ b/lily/note-spacing-engraver.cc @@ -0,0 +1,99 @@ +#if 0 +/* + note-spacing-engraver.cc -- implement Note_spacing_engraver. + + source file of the GNU LilyPond music typesetter + + (c) 2001 Han-Wen Nienhuys + +*/ + +#include "grob.hh" +#include "moment.hh" +#include "engraver.hh" +#include "note-spacing.hh" +#include "note-column.hh" + +/* + Originally, we tried to have this functionality at Staff_level + + - by simply using the sequence of Separation-item as + spacing-sequences. Unfortunately, this fucks up if there are + different kinds of tuplets combined (8th and 8ths triplets combined + made the program believe there were 1/12 th notes.). + + + - We also created them from Rhythmic_column_engraver, but this has + the problem that voices can appear and disappear at will, leaving + lots of loose ends (the StaffSpacing don't know where to connect the + last note of the voice on the right with) + + */ + +struct Grob_moment_tuple +{ + Link_array current_heads_; + Link_array todo_heads_; + + Moment length_; + + static int time_compare (Grob_moment_tuple const &a, Grob_moment_tuple const &b) + { + return Moment::compare (a.length_, b.length_); + } +}; + +class Note_spacing_engraver : public Engraver +{ +public: + TRANSLATOR_DECLARATIONS(Note_spacing_engraver); + + +protected: + Array lengths_found_; + + virtual void acknowledge_grob (Grob_info); +}; + +Note_spacing_engraver::Note_spacing_engraver() +{ +} + + +void +Note_spacing_engraver::acknowledge_grob (Grob_info gi) +{ + if (Note_head::has_interface (gi.grob_l_)) + { + Music *m = gi.music_cause(); + Moment now = now_mom (); + Moment len = m->length_mom(); + if (now.grace_part_ && len.main_part_) + { + len.grace_part_ += len.main_part_; + len.main_part_ = 0; + } + + for (int i=0; i < + } + Note_column::has_interface (gi.grob_l_)) + { + Grob *head =Note_column::first_head (gi.grob_l_); + + head-> + } +} + + + +ENTER_DESCRIPTION(Note_spacing_engraver, +/* descr */ "This engraver creates spacing objects. It should be placed at staff +level, but will also function at voice level. + +", +/* creats*/ "NoteSpacing", +/* acks */ "rhythmic-column-interface", +/* reads */ "", +/* write */ ""); + +#endif diff --git a/lily/note-spacing.cc b/lily/note-spacing.cc index 81eb2aa03b..0628ffab82 100644 --- a/lily/note-spacing.cc +++ b/lily/note-spacing.cc @@ -1,17 +1,88 @@ /* -note-spacing.cc -- implement + note-spacing.cc -- implement Note_spacing -source file of the GNU LilyPond music typesetter + source file of the GNU LilyPond music typesetter -(c) 2001 Han-Wen Nienhuys + (c) 2001 Han-Wen Nienhuys +*/ - */ +#include "paper-column.hh" +#include "item.hh" +#include "moment.hh" #include "note-spacing.hh" #include "grob.hh" +#include "note-column.hh" +#include "warn.hh" bool Note_spacing::has_interface (Grob* g) { return g && g->has_interface (ly_symbol2scm ("note-spacing-interface")); } + + + +Real +Note_spacing::get_spacing (Grob *me) +{ + Drul_array props(me->get_grob_property ("left-items"), + me->get_grob_property ("right-items")); + Direction d = LEFT; + Drul_array extents; + do + { + for (SCM s = props[d]; gh_pair_p (s); s = gh_cdr (s)) + { + Item * it= dynamic_cast (unsmob_grob (gh_car(s))); + extents[d].unite (it->extent (it->column_l (), X_AXIS)); + + if (d == RIGHT) + { + Grob * accs = Note_column::accidentals (it); + if (accs) + extents[d].unite (accs->extent (it->column_l (), X_AXIS)); + } + } + + if (extents[d].empty_b ()) + extents[d] = Interval (0,0); + } + while (flip (&d) != LEFT); + + /* + + What's sticking out at the left of the right side has less + influence. + + */ + Real dx= extents[LEFT][RIGHT] - 0.5 * extents[RIGHT][LEFT]; + return dx; +} + + +MAKE_SCHEME_CALLBACK(Note_spacing, before_line_breaking, 1) +SCM +Note_spacing::before_line_breaking (SCM g) +{ + Grob * me = unsmob_grob (g); + SCM right = me->get_grob_property ("right-items"); + + if (gh_pair_p (right)) + right = gh_car (right); + + Grob *right_grob = unsmob_grob (right); + + Item * ri = dynamic_cast (right_grob); + if (!ri) + { + int r = Paper_column::rank_i (dynamic_cast(me)->column_l ()); + programming_error (_f("Spacing wish column %d has no right item.", r)); + } + else + { + me->set_grob_property ("right-column", ri->column_l ()->self_scm()); + } + + return SCM_UNSPECIFIED; +} diff --git a/lily/paper-column.cc b/lily/paper-column.cc index 14774ed651..789a9cfa73 100644 --- a/lily/paper-column.cc +++ b/lily/paper-column.cc @@ -5,12 +5,32 @@ (c) 1997--2001 Han-Wen Nienhuys */ + #include "moment.hh" #include "paper-column.hh" #include "paper-score.hh" #include "debug.hh" #include "axis-group-interface.hh" #include "spaceable-grob.hh" +#include "molecule.hh" +#include "text-item.hh" +#include "lookup.hh" +#include "font-interface.hh" + + +/* + Paper_columns form the top-most item parent. (The Paper_columns X + parent is Line_of_score, which is a spanner.) + + Paper_columns form the units for the spacing engine. They are + numbered, the first (leftmost) is column 0. Numbering happens before + line-breaking, and columns are not renumbered after line breaking. + + Since many columns go unused, you should only use the rank field to + get ordering information. Two adjacent columns may have + non-adjacent numbers. + + */ void Paper_column::do_break_processing () @@ -73,6 +93,7 @@ Paper_column::musical_b (Grob *me) } + bool Paper_column::used_b (Grob*me) { @@ -80,3 +101,29 @@ Paper_column::used_b (Grob*me) || gh_pair_p (me->get_grob_property ("bounded-by-me")) ; } + +/* + Print a vertical line and the rank number, to aid debugging. + */ + +MAKE_SCHEME_CALLBACK(Paper_column,brew_molecule,1); +SCM +Paper_column::brew_molecule (SCM p) +{ + Grob *me = unsmob_grob (p); + + String r = to_str (Paper_column::rank_i (me)); + SCM properties = Font_interface::font_alist_chain (me); + + Molecule t = Text_item::text2molecule (me, ly_str02scm (r.ch_C()), + properties); + t.align_to (X_AXIS, CENTER); + t.align_to (Y_AXIS, DOWN); + + Molecule l = Lookup::filledbox (Box (Interval (-0.01, 0.01), + Interval (-2, -1))); + + t.add_molecule (l); + return t.smobbed_copy (); +} + diff --git a/lily/rhythmic-column-engraver.cc b/lily/rhythmic-column-engraver.cc index c87409c450..84bd2ae16c 100644 --- a/lily/rhythmic-column-engraver.cc +++ b/lily/rhythmic-column-engraver.cc @@ -58,15 +58,6 @@ Rhythmic_column_engraver::create_grobs () note_column_ = new Item (get_property ("NoteColumn")); Note_column::set_interface (note_column_); announce_grob (note_column_, 0); - - spacing_ = new Item (get_property ("NoteSpacing")); - spacing_->set_grob_property ("left-item", note_column_->self_scm ()); - announce_grob (spacing_, 0); - - if (last_spacing_) - { - last_spacing_->set_grob_property ("right-item" , note_column_->self_scm ()); - } } for (int i=0; i < rhead_l_arr_.size (); i++) diff --git a/lily/separating-line-group-engraver.cc b/lily/separating-line-group-engraver.cc index fc8679494f..57100c952e 100644 --- a/lily/separating-line-group-engraver.cc +++ b/lily/separating-line-group-engraver.cc @@ -15,6 +15,27 @@ #include "axis-group-interface.hh" #include "note-spacing.hh" + +struct Spacings +{ + Item * staff_spacing_; + Link_array note_spacings_; + + Spacings () + { + staff_spacing_ = 0; + } + + bool empty( )const + { + return !staff_spacing_ && !note_spacings_.size (); + } + void clear () { + staff_spacing_ = 0; + note_spacings_.clear(); + } +}; + class Separating_line_group_engraver : public Engraver { protected: @@ -22,9 +43,8 @@ protected: Item * musical_malt_p_; Item * last_musical_malt_p_; - Item * last_note_spacing_; - Item * current_note_spacing_; - Item * staff_spacing_; + Spacings current_spacings_; + Spacings last_spacings_; Spanner * sep_span_p_; @@ -32,16 +52,13 @@ protected: virtual void initialize (); virtual void finalize (); virtual void stop_translation_timestep (); + virtual void start_translation_timestep (); public: TRANSLATOR_DECLARATIONS(Separating_line_group_engraver); }; Separating_line_group_engraver::Separating_line_group_engraver () { - last_note_spacing_ = 0; - current_note_spacing_ = 0; - staff_spacing_ =0; - sep_span_p_ = 0; break_malt_p_ = 0; musical_malt_p_ =0; @@ -59,9 +76,21 @@ Separating_line_group_engraver::initialize () void Separating_line_group_engraver::finalize () { - sep_span_p_->set_bound (RIGHT, unsmob_grob (get_property ("currentCommandColumn"))); + SCM ccol = get_property ("currentCommandColumn"); + sep_span_p_->set_bound (RIGHT, unsmob_grob (ccol)); typeset_grob (sep_span_p_); sep_span_p_ =0; + + for (int i= 0 ; i < last_spacings_.note_spacings_.size(); i++) + { + last_spacings_.note_spacings_[i]->set_grob_property ("right-items", gh_cons (ccol, SCM_EOL)); + } + + if(last_spacings_.staff_spacing_ + && last_spacings_.staff_spacing_->column_l () == unsmob_grob (ccol)) + { + last_spacings_.staff_spacing_->suicide (); + } } void @@ -77,7 +106,7 @@ Separating_line_group_engraver::acknowledge_grob (Grob_info i) if (Note_spacing::has_interface (it)) { - current_note_spacing_ = it; + current_spacings_.note_spacings_.push (it); return ; } @@ -95,19 +124,38 @@ Separating_line_group_engraver::acknowledge_grob (Grob_info i) if (p_ref_ == break_malt_p_) { - staff_spacing_ = new Item (get_property ("StaffSpacing")); - staff_spacing_->set_grob_property ("left-item", break_malt_p_->self_scm ()); - announce_grob (staff_spacing_, 0); - - if (last_note_spacing_) - last_note_spacing_->set_grob_property ("right-item", - break_malt_p_->self_scm ()); + Item *it = new Item (get_property ("StaffSpacing")); + current_spacings_.staff_spacing_ = it; + it->set_grob_property ("left-items", gh_cons (break_malt_p_->self_scm (), SCM_EOL)); + + announce_grob (it, 0); + + if (int i = last_spacings_.note_spacings_.size ()) + { + SCM break_malt = gh_cons (break_malt_p_->self_scm (), SCM_EOL); + for (; i--;) + last_spacings_.note_spacings_[i] + ->set_grob_property ("right-items",break_malt); + + } + else if (last_spacings_.staff_spacing_) + { + + last_spacings_.staff_spacing_->set_grob_property ("right-items", + gh_cons (break_malt_p_->self_scm(), SCM_EOL)); + } } } Separation_item::add_item (p_ref_,it); } +void +Separating_line_group_engraver::start_translation_timestep () +{ + +} + void Separating_line_group_engraver::stop_translation_timestep () { @@ -119,23 +167,30 @@ Separating_line_group_engraver::stop_translation_timestep () break_malt_p_ =0; } - if (staff_spacing_) + if (Item * sp = current_spacings_.staff_spacing_) { + /* + TODO: should really look at the left-items of following + note-spacing grobs. + */ if (musical_malt_p_) - staff_spacing_->set_grob_property ("right-item", musical_malt_p_->self_scm()); + sp->set_grob_property ("right-items", musical_malt_p_->self_scm()); + + typeset_grob (sp); + } - typeset_grob (staff_spacing_); - staff_spacing_ = 0; + if (!current_spacings_.empty ()) + { + last_spacings_ = current_spacings_; } + + current_spacings_.clear (); if (musical_malt_p_) { Separating_group_spanner::add_spacing_unit (sep_span_p_, musical_malt_p_); typeset_grob (musical_malt_p_); } - - last_note_spacing_ = current_note_spacing_ ; - current_note_spacing_ =0 ; musical_malt_p_ =0; } diff --git a/lily/spacing-wish.cc b/lily/spacing-wish.cc new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/lily/spacing-wish.cc @@ -0,0 +1 @@ + diff --git a/lily/staff-spacing.cc b/lily/staff-spacing.cc index 771760ca52..a662f54133 100644 --- a/lily/staff-spacing.cc +++ b/lily/staff-spacing.cc @@ -15,3 +15,4 @@ Staff_spacing::has_interface (Grob* g) { return g && g->has_interface (ly_symbol2scm ("staff-spacing-interface")); } + diff --git a/lily/stem-engraver.cc b/lily/stem-engraver.cc index 5ab49f9227..aba73c027f 100644 --- a/lily/stem-engraver.cc +++ b/lily/stem-engraver.cc @@ -105,6 +105,10 @@ Stem_engraver::acknowledge_grob (Grob_info i) gh_int2scm (tremolo_flags)); } } + + /* + We announce the cause of the head as cause of the stem. + The stem needs a rhythmic structure to fit it into a beam. */ announce_grob (stem_p_, i.music_cause ()); } diff --git a/lily/text-item.cc b/lily/text-item.cc index e4320a3daf..1f83982d06 100644 --- a/lily/text-item.cc +++ b/lily/text-item.cc @@ -122,9 +122,18 @@ Text_item::lookup_text (Grob *me, Font_metric*fm, SCM text) return Molecule (fm->text_dimension (ly_scm2string (text)), list); } +/* + TODO: + + DOCME. + + + MARKUP_TEXT must be compound (may not be simple string.) + + */ Molecule Text_item::markup_text2molecule (Grob *me, SCM markup_text, - SCM alist_chain) + SCM alist_chain) { SCM sheet = me->paper_l ()->style_sheet_; SCM f = ly_cdr (scm_assoc (ly_symbol2scm ("markup-to-properties"), sheet)); diff --git a/lily/translator-group.cc b/lily/translator-group.cc index aac575c38b..34e8d0c63e 100644 --- a/lily/translator-group.cc +++ b/lily/translator-group.cc @@ -247,7 +247,7 @@ static void static_each (SCM list, Method_pointer method) { for (SCM p = list; gh_pair_p (p); p = ly_cdr (p)) - (unsmob_translator (ly_car (p))->*method) (); + (unsmob_translator (ly_car (p))->*method) (); } diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly index 003d380d3f..0e1f1e7181 100644 --- a/ly/engraver-init.ly +++ b/ly/engraver-init.ly @@ -31,7 +31,8 @@ StaffContext=\translator { \consists "Accidental_engraver" \consists "Piano_pedal_engraver" \consists "Instrument_name_engraver" - + \consists "Grob_pq_engraver" + \consistsend "Axis_group_engraver" MinimumVerticalExtent = #'(-4 . 4) diff --git a/scm/grob-description.scm b/scm/grob-description.scm index fd68506d0d..3938da7413 100644 --- a/scm/grob-description.scm +++ b/scm/grob-description.scm @@ -529,7 +529,9 @@ )) (SpacingSpanner . ( - (spacing-procedure . ,Spacing_spanner::set_springs) + (spacing-procedure . ;; ,Third_spacing_spanner::set_springs + ,Spacing_spanner::set_springs + ) (stem-spacing-correction . 0.5) (grace-space-factor . 0.8) diff --git a/scm/grob-property-description.scm b/scm/grob-property-description.scm index 0df5480c15..0d018c3d97 100644 --- a/scm/grob-property-description.scm +++ b/scm/grob-property-description.scm @@ -248,7 +248,8 @@ FIXME: also pair? (cons LEFT RIGHT) (grob-property-description 'non-default boolean? "not set because of existence of a bar?.") (grob-property-description 'note-character string? "character to print in a note head.") (grob-property-description 'note-width number? "unit for horizontal translation, measured in staff-space.") -(grob-property-description 'number-gap number? "size of the gap for the number in a tuplet.") +(grob-property-description 'note-heads list? "List of note head grobs") +(grob-property-description 'number-gap number? "size of the gap for tohe number in a tuplet.") (grob-property-description 'old-accidentals list? "list of (pitch, accidental) pairs.") (grob-property-description 'origin ly-input-location? "location in input file of the definition.") (grob-property-description 'outer-stem-length-limit number? "catch diff --git a/scm/interface-description.scm b/scm/interface-description.scm index 1e2fda7b37..ce5f960c3f 100644 --- a/scm/interface-description.scm +++ b/scm/interface-description.scm @@ -122,6 +122,7 @@ 'note-column-interface "Stem and noteheads combined" '( + note-heads horizontal-shift force-hshift )) diff --git a/scm/translator-property-description.scm b/scm/translator-property-description.scm index f5b1adaf40..93aabd8cdd 100644 --- a/scm/translator-property-description.scm +++ b/scm/translator-property-description.scm @@ -141,6 +141,10 @@ key signatures after the bar lines: ) @end example ") +(translator-property-description 'busyGrobs list? " +a queue of (END-MOMENT . GROB) conses. This is for internal (C++) use only. +Use at your own risk. +") (translator-property-description 'centralCPosition number? "Place of the central C. Usually determined by looking at clefPosition and clefGlyph.") (translator-property-description 'changeMoment moment-pair? "duration that voices are examined for differences, when part-combining. Usually unset or zero when combining threads into one voice, and 1 (or the duration of one measure) when combining voices into one staff.") (translator-property-description 'chordChanges boolean? "Only show changes in chords scheme?")