From: Han-Wen Nienhuys Date: Sat, 20 Apr 2002 23:02:57 +0000 (+0000) Subject: '' X-Git-Tag: release/1.5.53~4 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=b1a2da9808d72008166aec4c7af9f923ca38064b;p=lilypond.git '' --- diff --git a/ChangeLog b/ChangeLog index 88c06822af..14362a3a16 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,27 @@ +2002-04-21 Han-Wen + + * lily/include/accidental-placement.hh: new file. + + * lily/accidental-placement.cc (alignment_callback): position + accidentals in a better way. + + * lily/skyline.cc: new file. Compute distances for collections of boxes. + + * lily/include/skyline.hh: new file + 2002-04-20 Han-Wen + * lily/accidental.cc (class Accidental_interface): grob for single + accidental. + + * lily/accidental-engraver.cc (number_accidentals): Cleanups. Lots + of reformatting + + * lily/new-accidental-engraver.cc (acknowledge_grob): Work + together with new accidental-interface. + + * lily/include/*.hh: remove spurious set_interface() decls. + * lily/key-signature-interface.cc (brew_molecule): add padding for natural signs. Make natural typesetting like the sharp. diff --git a/NEWS b/NEWS index 4dd7ec9c36..70bc947d14 100644 --- a/NEWS +++ b/NEWS @@ -14,3 +14,5 @@ New features in 1.5 * More ancient notation support. * Some entry optimizations. + +* Font updated and improved. diff --git a/lily/accidental-engraver.cc b/lily/accidental-engraver.cc index 8a3110cfb6..6ee866df9b 100644 --- a/lily/accidental-engraver.cc +++ b/lily/accidental-engraver.cc @@ -24,11 +24,11 @@ /** - FIXME: should not compute vertical positioning of accidentals, but - get them from the noteheads +FIXME: should not compute vertical positioning of accidentals, but +get them from the noteheads - The algorithm for accidentals should be documented, and made - tweakable. +The algorithm for accidentals should be documented, and made +tweakable. */ @@ -36,7 +36,7 @@ struct Accidental_engraver : Engraver { Item *key_item_p_; protected: - TRANSLATOR_DECLARATIONS(Accidental_engraver); + TRANSLATOR_DECLARATIONS (Accidental_engraver); virtual void process_music (); virtual void acknowledge_grob (Grob_info); virtual void stop_translation_timestep (); @@ -45,13 +45,20 @@ protected: virtual void finalize (); public: - // todo -> property (why? -rz) + /* + TODO -> property. + + This is not a property, and it is not protected. This poses a + very small risk of the value being GC'd from under us. + + Oh well. + */ SCM last_keysig_; /* Urgh. Since the accidentals depend on lots of variables, we have to store all information before we can really create the accidentals. - */ + */ Link_array arpeggios_; Link_array mel_l_arr_; @@ -65,7 +72,7 @@ public: Accidental_engraver::Accidental_engraver () { - key_item_p_ =0; + key_item_p_ = 0; last_keysig_ = SCM_EOL; } @@ -75,97 +82,126 @@ Accidental_engraver::initialize () last_keysig_ = get_property ("keySignature"); Translator_group * trans_ = daddy_trans_l_; - while (trans_) { - trans_ -> set_property ("localKeySignature", ly_deep_copy(last_keysig_)); - trans_ = trans_->daddy_trans_l_; - } - daddy_trans_l_->set_children_property("localKeySignature",last_keysig_); - + while (trans_) + { + trans_ -> set_property ("localKeySignature", ly_deep_copy (last_keysig_)); + trans_ = trans_->daddy_trans_l_; + } + daddy_trans_l_->set_children_property ("localKeySignature", last_keysig_); } -/** calculates the number of accidentals on basis of the current local key sig - * (passed as argument) - * Returns number of accidentals (0, 1 or 2). - * Negative (-1 or -2) if accidental has changed. - **/ -// FIXME: Use references for SCM-values +/* + +calculates the number of accidentals on basis of the current local key sig + (passed as argument) + Returns number of accidentals (0, 1 or 2). + Negative (-1 or -2) if accidental has changed. + +*/ static int -number_accidentals (SCM sig, Note_req * note_l, SCM curbarnum, SCM lazyness, +number_accidentals (SCM sig, Note_req * note_l, SCM curbarnum, SCM lazyness, bool ignore_octave_b) { Pitch *pitch = unsmob_pitch (note_l->get_mus_property ("pitch")); int n = pitch->notename_i_; int o = pitch->octave_i_; int a = pitch->alteration_i_; - int curbarnum_i = gh_scm2int(curbarnum); + int curbarnum_i = gh_scm2int (curbarnum); int accbarnum_i = 0; + SCM prev; if (ignore_octave_b) prev = ly_assoc_cdr (gh_int2scm (n), sig); else prev = gh_assoc (gh_cons (gh_int2scm (o), gh_int2scm (n)), sig); - /* should really be true unless prev==SCM_BOOL_F */ - if(gh_pair_p(prev) && gh_pair_p(ly_cdr(prev))) { - accbarnum_i = gh_scm2int(ly_cddr(prev)); - prev = gh_cons(ly_car(prev),ly_cadr(prev)); - } + + /* should really be true unless prev == SCM_BOOL_F */ + if (gh_pair_p (prev) && gh_pair_p (ly_cdr (prev))) + { + accbarnum_i = gh_scm2int (ly_cddr (prev)); + prev = gh_cons (ly_car (prev), ly_cadr (prev)); + } + /* If an accidental was not found or the accidental was too old */ if (prev == SCM_BOOL_F || - (gh_number_p(lazyness) && curbarnum_i>accbarnum_i+gh_scm2int(lazyness))) + (gh_number_p (lazyness) && curbarnum_i > accbarnum_i + gh_scm2int (lazyness))) prev = gh_assoc (gh_int2scm (n), sig); + + SCM prev_acc = (prev == SCM_BOOL_F) ? gh_int2scm (0) : ly_cdr (prev); int p = gh_number_p (prev_acc) ? gh_scm2int (prev_acc) : 0; int num; - if (a==p && !to_boolean (note_l->get_mus_property ("force-accidental")) && gh_number_p(prev_acc)) num=0; - else if ( (abs(a)get_mus_property ("force-accidental")) + && gh_number_p (prev_acc)) + num = 0; + else if ( (abs (a)get_property ("localKeySignature"); - bool same_octave_b = - gh_eq_p(ly_symbol2scm("same-octave"),type); - bool any_octave_b = - gh_eq_p(ly_symbol2scm("any-octave"),type); - if(same_octave_b || any_octave_b) { - int n = number_accidentals - (localsig,note_l,curbarnum_s,lazyness,any_octave_b); - diff |= n<0; - number = max(number,abs(n)); - } - else warning(_f("unknown accidental typesetting: %s. Ignored", - ly_symbol2string(type).ch_C())); - } - // if symbol then it is a context name. Scan parent contexts to find it. - else if (gh_symbol_p(ly_car(accidentals_sl))) { - String context = ly_symbol2string(ly_car(accidentals_sl)); - while (origin_l && !origin_l->is_alias_b(context)) { - origin_l = origin_l->daddy_trans_l_; - } - if (!origin_l) - warning(_f("Symbol is not a parent context: %s. Ignored", - context.ch_C())); +static int +number_accidentals (Note_req * note_l, Translator_group * origin_l, + SCM accidentals, SCM curbarnum) +{ + int number = 0; + + bool diff = false; + if (gh_pair_p (accidentals) && !gh_symbol_p (ly_car (accidentals))) + warning (_f ("Accidental typesetting list must begin with context-name: %s", + ly_scm2string (ly_car (accidentals)).ch_C ())); + + while (gh_pair_p (accidentals) && origin_l) + { + // If pair then it is a new accidentals typesetting rule to be checked + if (gh_pair_p (ly_car (accidentals))) + { + SCM type = gh_caar (accidentals); + SCM lazyness = gh_cdar (accidentals); + SCM localsig = origin_l->get_property ("localKeySignature"); + + bool same_octave_b = + gh_eq_p (ly_symbol2scm ("same-octave"), type); + bool any_octave_b = + gh_eq_p (ly_symbol2scm ("any-octave"), type); + + if (same_octave_b || any_octave_b) + { + int n = number_accidentals + (localsig, note_l, curbarnum, lazyness, any_octave_b); + diff = diff || (n < 0); + number = max (number, abs (n)); + } + else + warning (_f ("unknown accidental typesetting: %s. Ignored", + ly_symbol2string (type).ch_C ())); + } + + + /* + if symbol then it is a context name. Scan parent contexts to find it. + */ + else if (gh_symbol_p (ly_car (accidentals))) + { + String context = ly_symbol2string (ly_car (accidentals)); + + while (origin_l && !origin_l->is_alias_b (context)) + origin_l = origin_l->daddy_trans_l_; + + if (!origin_l) + warning (_f ("Symbol is not a parent context: %s. Ignored", + context.ch_C ())); + } + else warning (_f ("Accidental typesetting must be pair or context-name: %s", + ly_scm2string (ly_car (accidentals)).ch_C ())); + + accidentals = ly_cdr (accidentals); } - else warning(_f("Accidental typesetting must be pair or context-name: %s", - ly_scm2string(ly_car(accidentals_sl)).ch_C())); - accidentals_sl = ly_cdr(accidentals_sl); - } return diff ? -number : number; } @@ -175,46 +211,47 @@ Accidental_engraver::create_grobs () if (!key_item_p_ && mel_l_arr_.size ()) { //SCM localsig = get_property ("localKeySignature"); - SCM accidentals_sl = get_property ("autoAccidentals"); - SCM cautionaries_sl = get_property ("autoCautionaries"); + SCM accidentals = get_property ("autoAccidentals"); + SCM cautionaries = get_property ("autoCautionaries"); 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++) + bool extra_natural_b = get_property ("extraNatural") == SCM_BOOL_T; + for (int i = 0; i < mel_l_arr_.size (); i++) { Grob * support_l = head_l_arr_[i]; Note_req * note_l = mel_l_arr_[i]; Translator_group * origin_l = origin_l_arr_[i]; - int num = number_accidentals(note_l,origin_l,accidentals_sl,barnum); - int num_caut = number_accidentals(note_l,origin_l,cautionaries_sl,barnum); + int num = number_accidentals (note_l, origin_l, accidentals, barnum); + int num_caut = number_accidentals (note_l, origin_l, cautionaries, barnum); bool cautionary = to_boolean (note_l->get_mus_property ("cautionary")); - if (abs(num_caut)>abs(num)) + + if (abs (num_caut)>abs (num)) { - num=num_caut; - cautionary=true; + num = num_caut; + cautionary = true; } - bool different=num<0; - num=abs(num); + bool different = num < 0; + num = abs (num); /* see if there's a tie that "changes" the accidental */ /* works because if there's a tie, the note to the left is of the same pitch as the actual note */ - Grob *tie_break_reminder = 0; bool tie_changes = false; - for (int j=0; j < tie_l_arr_.size (); j++) + for (int j = 0; j < tie_l_arr_.size (); j++) if (support_l == Tie::head (tie_l_arr_[j], RIGHT)) { tie_changes = different; + /* Enable accidentals for broken tie - We only want an accidental on a broken tie, - if the tie changes the accidental. + We only want an accidental on a broken tie, + if the tie changes the accidental. - Maybe check property noTieBreakForceAccidental? */ + Maybe check property noTieBreakForceAccidental? */ if (different) tie_break_reminder = tie_l_arr_[j]; break; @@ -230,15 +267,15 @@ Accidental_engraver::create_grobs () if (gh_number_p (c0)) Staff_symbol_referencer::set_position (key_item_p_, gh_scm2int (c0)); - announce_grob(key_item_p_, SCM_EOL); + announce_grob (key_item_p_, SCM_EOL); } - Local_key_item::add_pitch (key_item_p_, *unsmob_pitch (note_l->get_mus_property ("pitch")), - cautionary, - num==2 && extra_natural_b, + Local_key_item::add_pitch (key_item_p_, *unsmob_pitch (note_l->get_mus_property ("pitch")), + cautionary, + num == 2 && extra_natural_b, tie_break_reminder); - Side_position_interface::add_support (key_item_p_,support_l); + Side_position_interface::add_support (key_item_p_, support_l); support_l->set_grob_property ("accidentals-grob", key_item_p_->self_scm ()); } @@ -250,7 +287,7 @@ Accidental_engraver::create_grobs () Checking whether it is tied also works mostly, but will it always do the correct thing? - */ + */ Pitch *pitch = unsmob_pitch (note_l->get_mus_property ("pitch")); int n = pitch->notename_i_; @@ -260,33 +297,46 @@ Accidental_engraver::create_grobs () /* TODO: Speed this up! + Perhaps only check translators mentioned in the auto-accidentals? -rz + + TODO: profile this. + + I'd be surprised if the impact of this would be + measurable. Anyway, it seems localsig doesn't change + every time-step, but a set_property() is done every + time. We could save on that, probably. + + --hwn. + + */ Translator_group * trans_ = origin_l_arr_[i]; - while (trans_) { - SCM localsig = trans_->get_property ("localKeySignature"); - if (tie_changes) - { - /* - Remember an alteration that is different both from - that of the tied note and of the key signature. - */ - localsig = ly_assoc_front_x - (localsig, on_s, gh_cons(SCM_BOOL_T,barnum)); - } - else - { - /* - not really really correct if there are more than one - noteheads with the same notename. - */ - localsig = ly_assoc_front_x - (localsig, on_s, gh_cons(gh_int2scm (a),barnum)); - } - trans_->set_property ("localKeySignature", localsig); - trans_ = trans_->daddy_trans_l_; - } + while (trans_) + { + SCM localsig = trans_->get_property ("localKeySignature"); + if (tie_changes) + { + /* + Remember an alteration that is different both from + that of the tied note and of the key signature. + */ + localsig = ly_assoc_front_x + (localsig, on_s, gh_cons (SCM_BOOL_T, barnum)); + } + else + { + /* + not really really correct if there are more than one + noteheads with the same notename. + */ + localsig = ly_assoc_front_x + (localsig, on_s, gh_cons (gh_int2scm (a), barnum)); + } + trans_->set_property ("localKeySignature", localsig); + trans_ = trans_->daddy_trans_l_; + } } } @@ -297,8 +347,8 @@ Accidental_engraver::create_grobs () 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++) + */ + for (int i = 0; i < arpeggios_.size (); i++) Side_position_interface::add_support (arpeggios_[i], key_item_p_); arpeggios_.clear (); @@ -316,11 +366,11 @@ Accidental_engraver::stop_translation_timestep () { if (key_item_p_) { - for (int i=0; i < head_l_arr_.size (); i++) - Side_position_interface::add_support (key_item_p_,head_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; + key_item_p_ = 0; } @@ -357,38 +407,35 @@ Accidental_engraver::acknowledge_grob (Grob_info info) void Accidental_engraver::process_music () { -#if 0 - SCM smp = get_property ("measurePosition"); - Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0); -#endif - SCM sig = get_property ("keySignature"); /* Detect key sig changes. Update all parents and children - */ - if (last_keysig_ != sig) { - Translator_group * trans_ = daddy_trans_l_; - while (trans_) { - trans_ -> set_property ("localKeySignature", ly_deep_copy(sig)); - trans_ = trans_->daddy_trans_l_; - } - daddy_trans_l_->set_children_property("localKeySignature",sig); + */ + if (last_keysig_ != sig) + { + Translator_group * trans_ = daddy_trans_l_; + while (trans_) + { + trans_ -> set_property ("localKeySignature", ly_deep_copy (sig)); + trans_ = trans_->daddy_trans_l_; + } + daddy_trans_l_->set_children_property ("localKeySignature", sig); - last_keysig_ = sig; - } + last_keysig_ = sig; + } } -ENTER_DESCRIPTION(Accidental_engraver, -/* The FIXME below is deprecated and should be removed. -rz */ -/* descr */ "Make accidentals. Catches note heads, ties and notices key-change +ENTER_DESCRIPTION (Accidental_engraver, +"Make accidentals. Catches note heads, ties and notices key-change events. Due to interaction with ties (which don't come together -with note heads), this needs to be in a context higher than Tie_engraver. FIXME", -/* creats*/ "Accidentals", -/* acks */ "rhythmic-head-interface tie-interface arpeggio-interface", -/* reads */ "localKeySignature extraNatural autoAccidentals autoCautionaries", -/* write */ "localKeySignature"); +with note heads), this needs to be in a context higher than Tie_engraver.", + + "Accidentals", + "rhythmic-head-interface tie-interface arpeggio-interface", + "localKeySignature extraNatural autoAccidentals autoCautionaries", + "localKeySignature"); diff --git a/lily/accidental-placement.cc b/lily/accidental-placement.cc new file mode 100644 index 0000000000..3d1179c434 --- /dev/null +++ b/lily/accidental-placement.cc @@ -0,0 +1,166 @@ +/* +accidental-placement.cc -- implement Accidental_placement + +source file of the GNU LilyPond music typesetter + +(c) 2002 Han-Wen Nienhuys + + */ + + +#include "item.hh" +#include "skyline.hh" +#include "music.hh" +#include "pitch.hh" +#include "warn.hh" +#include "accidental-placement.hh" + + +MAKE_SCHEME_CALLBACK(Accidental_placement,alignment_callback, 2); +SCM +Accidental_placement::alignment_callback(SCM s, SCM ) +{ + Grob * me =unsmob_grob (s); + + Grob * par = me->get_parent (X_AXIS); + if (!to_boolean (par->get_grob_property ("done"))) + { + par->set_grob_property ("done", SCM_BOOL_T); + position_accidentals (par); + } + + + return gh_int2scm (0); +} + +void +Accidental_placement::add_accidental (Grob* me, Grob* a) +{ + a->set_parent (me, X_AXIS); + a->add_offset_callback (alignment_callback_proc, X_AXIS); + SCM cause = a->get_parent (Y_AXIS)->get_grob_property("cause"); + + Music *mcause =unsmob_music (cause); + if (!mcause) + { + programming_error ("Note head has no music cause!"); + return; + } + + Pitch *p= unsmob_pitch (mcause->get_mus_property ("pitch")); + + int n = p->notename_i_; + + SCM accs = me->get_grob_property ("accidentals"); + SCM key = gh_int2scm (n); + SCM entry = scm_assq (key, accs); + if (entry == SCM_BOOL_F) + { + entry = SCM_EOL; + } + else + entry = gh_cdr (entry); + + entry = gh_cons (a->self_scm (), entry); + + accs = scm_assq_set_x (accs, key, entry); + + me->set_grob_property ("accidentals", accs); +} + + +struct Accidental_placement_entry +{ + Array left_skyline_; + Array right_skyline_; + Interval vertical_extent_; + Array extents_; + Link_array grobs_; + int notename_; +}; + +int ape_compare (Accidental_placement_entry *const &a, + Accidental_placement_entry *const &b) +{ + return sign (a->vertical_extent_.length () - b->vertical_extent_.length()); +} + +void +Accidental_placement::position_accidentals (Grob * me) +{ + SCM accs = me->get_grob_property ("accidentals"); + + Link_array apes; + for (SCM s = accs; gh_pair_p (s); s =gh_cdr (s)) + { + Accidental_placement_entry *ape = new Accidental_placement_entry; + ape->notename_ = gh_scm2int (gh_caar (s)); + + for (SCM t = gh_cdar (s); gh_pair_p (t); t =gh_cdr (t)) + ape->grobs_.push (unsmob_grob (gh_car (t))); + + apes.push (ape); + } + + + Grob *commony =0 ; + for (int i= apes.size (); i--;) + for (int j = apes[i]->grobs_.size(); j--;) + { + Grob * a = apes[i]->grobs_[j]; + + if (commony) + commony =commony->common_refpoint (a, Y_AXIS); + else + commony =a; + } + + for (int i= apes.size (); i--;) + { + Interval y ; + + for (int j = apes[i]->grobs_.size(); j--;) + { + Grob * a = apes[i]->grobs_[j]; + Box b; + b[X_AXIS] = a->extent (me, X_AXIS); + b[Y_AXIS] = a->extent (commony, Y_AXIS); + + y.unite (b[Y_AXIS]); + apes[i]->extents_.push (b); + } + + apes[i]->vertical_extent_ = y; + } + + for (int i= apes.size (); i--;) + { + Accidental_placement_entry * ape = apes[i]; + ape->left_skyline_ = extents_to_skyline (apes[i]->extents_, Y_AXIS, LEFT); + ape->right_skyline_ = extents_to_skyline (apes[i]->extents_, Y_AXIS, RIGHT); + } + + apes.sort (&ape_compare); + + for (int i= apes.size ()-1; i-- > 0;) + { + Accidental_placement_entry *ape = apes[i]; + Real here = 0.0; + + Real d = skyline_meshing_distance (ape->right_skyline_, apes[i+1]->left_skyline_); + + here += d; + for (int j = ape->grobs_.size(); j--;) + { + ape->grobs_[j]->translate_axis (here, X_AXIS); + } + } + + for (int i = apes.size(); i--;) + delete apes[i]; +} + +ADD_INTERFACE(Accidental_placement, + "accidental-placement-interface", + "Take care of complex accidental collisions.", + "accidentals done") diff --git a/lily/accidental.cc b/lily/accidental.cc new file mode 100644 index 0000000000..44c26da035 --- /dev/null +++ b/lily/accidental.cc @@ -0,0 +1,70 @@ +#include "font-interface.hh" +#include "item.hh" +#include "molecule.hh" + +class Accidental_interface +{ +public: + DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM)); + static bool has_interface (Grob*); +}; + +Molecule +parenthesize (Grob*me, Molecule m) +{ + Molecule open = Font_interface::get_default_font (me)->find_by_name (String ("accidentals-leftparen")); + Molecule close = Font_interface::get_default_font (me)->find_by_name (String ("accidentals-rightparen")); + m.add_at_edge (X_AXIS, LEFT, Molecule (open), 0); + m.add_at_edge (X_AXIS, RIGHT, Molecule (close), 0); + + return m; +} + +MAKE_SCHEME_CALLBACK (Accidental_interface,brew_molecule,1); +SCM +Accidental_interface::brew_molecule (SCM smob) +{ + Grob *me = unsmob_grob (smob); + + SCM scm_style = me->get_grob_property ("style"); + + String style; + if (gh_symbol_p (scm_style)) + { + style = ly_scm2string (scm_symbol_to_string (scm_style)); + } + else + { + /* + preferably no name for the default style. + */ + style = ""; + } + + + Molecule mol; + for (SCM s = me->get_grob_property ("accidentals"); + gh_pair_p (s); s= gh_cdr (s)) + { + SCM entry = gh_car (s); + + + Molecule acc (Font_interface::get_default_font (me)-> + find_by_name (String ("accidentals-") + + style + + to_str (gh_scm2int(entry)))); + + mol.add_at_edge (X_AXIS, RIGHT, acc, 0.0); + } + + if (to_boolean (me->get_grob_property ("parenthesize"))) + mol = parenthesize (me, mol); + + return mol.smobbed_copy(); +} + + + +ADD_INTERFACE(Accidental_interface, "accidental-interface", + "a single accidental", + "accidentals parenthesize"); diff --git a/lily/axis-group-interface.cc b/lily/axis-group-interface.cc index 10ffa7172a..424eb53330 100644 --- a/lily/axis-group-interface.cc +++ b/lily/axis-group-interface.cc @@ -75,7 +75,6 @@ Axis_group_interface::group_extent_callback (SCM element_smob, SCM scm_axis) void Axis_group_interface::set_axes (Grob*me,Axis a1, Axis a2) { - // set_interface () ? SCM sa1= gh_int2scm (a1); SCM sa2 = gh_int2scm (a2); diff --git a/lily/include/align-interface.hh b/lily/include/align-interface.hh index b2ebee3b7d..d88898c176 100644 --- a/lily/include/align-interface.hh +++ b/lily/include/align-interface.hh @@ -23,7 +23,7 @@ struct Align_interface { static Axis axis (Grob*) ; static void add_element (Grob*,Grob*, SCM callback); static int get_count (Grob*,Grob*); - static void set_interface (Grob*); + static bool has_interface (Grob*); }; diff --git a/lily/include/axis-group-interface.hh b/lily/include/axis-group-interface.hh index ed9f991cfb..e990d2e738 100644 --- a/lily/include/axis-group-interface.hh +++ b/lily/include/axis-group-interface.hh @@ -25,7 +25,7 @@ struct Axis_group_interface static bool axis_b (Grob*,Axis); static Link_array get_children (Grob*); static bool has_interface (Grob*); - static void set_interface (Grob*); + }; diff --git a/lily/include/bar-line.hh b/lily/include/bar-line.hh index d0bb69c9c9..4b747f95f1 100644 --- a/lily/include/bar-line.hh +++ b/lily/include/bar-line.hh @@ -17,7 +17,7 @@ class Bar_line { public: static bool has_interface (Grob*); - static void set_interface (Grob*); + static Molecule compound_barline (Grob*, String, Real height) ; static Molecule simple_barline (Grob*, Real wid, Real height) ; DECLARE_SCHEME_CALLBACK (get_staff_bar_size, (SCM )); diff --git a/lily/include/bar.hh b/lily/include/bar.hh index 5132040ae7..6b5acda293 100644 --- a/lily/include/bar.hh +++ b/lily/include/bar.hh @@ -17,7 +17,7 @@ class Bar { public: static bool has_interface (Grob*); - static void set_interface (Grob*); + static Molecule compound_barline (Grob*, String, Real height) ; static Molecule simple_barline (Grob*, Real wid, Real height) ; DECLARE_SCHEME_CALLBACK (get_staff_bar_size, (SCM )); diff --git a/lily/include/break-align-interface.hh b/lily/include/break-align-interface.hh index cd0cf144c7..41aa1cc486 100644 --- a/lily/include/break-align-interface.hh +++ b/lily/include/break-align-interface.hh @@ -17,7 +17,7 @@ class Break_align_interface public: static void do_alignment (Grob*); static void new_do_alignment (Grob*); - static void set_interface (Grob*); + static bool has_interface (Grob*); static void add_element (Grob*me, Grob*add); DECLARE_SCHEME_CALLBACK (alignment_callback, (SCM element, SCM axis)); diff --git a/lily/include/breathing-sign.hh b/lily/include/breathing-sign.hh index f9a7a77887..96a99de992 100644 --- a/lily/include/breathing-sign.hh +++ b/lily/include/breathing-sign.hh @@ -21,7 +21,7 @@ class Breathing_sign public: DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM )); DECLARE_SCHEME_CALLBACK (offset_callback, (SCM element, SCM axis)); - static void set_interface (Grob*); + static bool has_interface (Grob*); }; diff --git a/lily/include/clef.hh b/lily/include/clef.hh index 7885205e7e..0f0d4f0ce9 100644 --- a/lily/include/clef.hh +++ b/lily/include/clef.hh @@ -17,7 +17,7 @@ struct Clef DECLARE_SCHEME_CALLBACK (before_line_breaking, (SCM )); DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM )); static bool has_interface (Grob*); - static void set_interface (Grob*); + }; diff --git a/lily/include/local-key-item.hh b/lily/include/local-key-item.hh index 8a2dd3199c..99bfbd135e 100644 --- a/lily/include/local-key-item.hh +++ b/lily/include/local-key-item.hh @@ -19,7 +19,6 @@ public: DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM)); static void add_pitch (Grob*me, Pitch, bool cautionary, bool natural, Grob *tie_break_cautionary); static bool has_interface (Grob*); - static void set_interface (Grob*); }; diff --git a/lily/include/multi-measure-rest.hh b/lily/include/multi-measure-rest.hh index 3ba796c515..2b73ba384e 100644 --- a/lily/include/multi-measure-rest.hh +++ b/lily/include/multi-measure-rest.hh @@ -17,7 +17,7 @@ class Multi_measure_rest { public: - static void set_interface (Grob*); + static bool has_interface (Grob*); DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM )); DECLARE_SCHEME_CALLBACK (percent, (SCM)); diff --git a/lily/include/note-column.hh b/lily/include/note-column.hh index 6ec04c2ee6..7279048660 100644 --- a/lily/include/note-column.hh +++ b/lily/include/note-column.hh @@ -40,7 +40,7 @@ public: static void add_head (Grob*me,Grob*); static bool rest_b (Grob*me); static bool has_interface (Grob*); - static void set_interface (Grob*); + static Item *stem_l (Grob*); }; diff --git a/lily/include/pitch.hh b/lily/include/pitch.hh index 0d30f0529f..d734189314 100644 --- a/lily/include/pitch.hh +++ b/lily/include/pitch.hh @@ -78,6 +78,7 @@ DECLARE_UNSMOB(Pitch,pitch); INSTANTIATE_COMPARE (Pitch, Pitch::compare); int compare (Array*, Array*); +extern SCM pitch_less_proc; #endif /* MUSICAL_PITCH_HH */ diff --git a/lily/include/rest-collision.hh b/lily/include/rest-collision.hh index 343c0e1cdd..b49e58dbc4 100644 --- a/lily/include/rest-collision.hh +++ b/lily/include/rest-collision.hh @@ -20,7 +20,7 @@ class Rest_collision { public: static void add_column (Grob*me,Grob*); - static void set_interface (Grob*me); + static bool has_interface (Grob*); DECLARE_SCHEME_CALLBACK (force_shift_callback, (SCM element, SCM axis)); static SCM do_shift (Grob*,SCM); diff --git a/lily/include/rhythmic-head.hh b/lily/include/rhythmic-head.hh index 7cb64250ca..af4af02ae8 100644 --- a/lily/include/rhythmic-head.hh +++ b/lily/include/rhythmic-head.hh @@ -23,7 +23,7 @@ public: static int dot_count (Grob*) ; DECLARE_SCHEME_CALLBACK (after_line_breaking, (SCM )); static bool has_interface (Grob*); - static void set_interface (Grob*); + }; #endif // RHYTHMIC_HEAD_HH diff --git a/lily/include/script.hh b/lily/include/script.hh index d2d10b8f79..41b7654b08 100644 --- a/lily/include/script.hh +++ b/lily/include/script.hh @@ -22,7 +22,7 @@ class Script { public: static Molecule get_molecule (Grob*,Direction d); - static void set_interface (Grob*); + static bool has_interface (Grob*); DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM )); DECLARE_SCHEME_CALLBACK (before_line_breaking, (SCM )); diff --git a/lily/include/separating-group-spanner.hh b/lily/include/separating-group-spanner.hh index 38f0e89288..37256f0310 100644 --- a/lily/include/separating-group-spanner.hh +++ b/lily/include/separating-group-spanner.hh @@ -17,7 +17,7 @@ class Separating_group_spanner public: static void add_spacing_unit (Grob*me, Item*); static void find_rods (Item*, SCM); - static void set_interface (Grob*); + static bool has_interface (Grob*); static void find_musical_sequences (Grob*); DECLARE_SCHEME_CALLBACK (set_spacing_rods, (SCM )); diff --git a/lily/include/skyline.hh b/lily/include/skyline.hh new file mode 100644 index 0000000000..0a477b8a7b --- /dev/null +++ b/lily/include/skyline.hh @@ -0,0 +1,34 @@ +/* + skyline.hh -- declare Skyline_entry and funcbs. + + source file of the GNU LilyPond music typesetter + + (c) 2002 Han-Wen Nienhuys +*/ + +#ifndef SKYLINE_HH +#define SKYLINE_HH + +#include "array.hh" +#include "box.hh" + +struct Skyline_entry +{ + Interval width_; + Real height_; + Skyline_entry(); + Skyline_entry (Interval, Real); +}; + +void +insert_extent_into_skyline (Array *line, Box b, Axis line_axis, + Direction d); +Array +extents_to_skyline (Array extents, Axis a, Direction d); +Real +skyline_meshing_distance (Array buildings, + Array clouds); + + +#endif /* SKYLINE_HH */ + diff --git a/lily/include/span-bar.hh b/lily/include/span-bar.hh index a6cd7960d1..56f4d2a0e5 100644 --- a/lily/include/span-bar.hh +++ b/lily/include/span-bar.hh @@ -21,7 +21,7 @@ class Span_bar { public: - static void set_interface (Grob*); + static bool has_interface (Grob*); static Interval get_spanned_interval (Grob*); static void add_bar (Grob*,Grob*); diff --git a/lily/include/staff-symbol-referencer.hh b/lily/include/staff-symbol-referencer.hh index c250e9e0d4..531497d988 100644 --- a/lily/include/staff-symbol-referencer.hh +++ b/lily/include/staff-symbol-referencer.hh @@ -21,7 +21,7 @@ class Staff_symbol_referencer { public: - static void set_interface (Grob*); + static bool has_interface (Grob*); static bool ugly_hack (Grob*); static void set_position (Grob*,Real); diff --git a/lily/include/staff-symbol.hh b/lily/include/staff-symbol.hh index 4043069cbf..497b7472fe 100644 --- a/lily/include/staff-symbol.hh +++ b/lily/include/staff-symbol.hh @@ -24,6 +24,6 @@ public: static int line_count (Grob*); DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM )); static bool has_interface (Grob*); - static void set_interface (Grob*); + }; #endif // STAFF_SYMBOL_HH diff --git a/lily/include/stem-tremolo.hh b/lily/include/stem-tremolo.hh index 1a6d9248e8..781d575016 100644 --- a/lily/include/stem-tremolo.hh +++ b/lily/include/stem-tremolo.hh @@ -16,7 +16,7 @@ class Stem_tremolo { public: - static void set_interface (Grob*); + static bool has_interface (Grob*); DECLARE_SCHEME_CALLBACK (dim_callback, (SCM smob, SCM axis)); DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM )); diff --git a/lily/include/system-start-delimiter.hh b/lily/include/system-start-delimiter.hh index 88ee130d2e..9765951fed 100644 --- a/lily/include/system-start-delimiter.hh +++ b/lily/include/system-start-delimiter.hh @@ -21,7 +21,7 @@ class System_start_delimiter public: DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM )); - static void set_interface (Grob*me); + static bool has_interface (Grob*); DECLARE_SCHEME_CALLBACK (after_line_breaking, (SCM )); static void try_collapse (Grob*); diff --git a/lily/include/volta-bracket.hh b/lily/include/volta-bracket.hh index fda29658e8..6beb4e05fd 100644 --- a/lily/include/volta-bracket.hh +++ b/lily/include/volta-bracket.hh @@ -14,9 +14,7 @@ class Volta_bracket_interface { public: - static void set_interface (Grob*); static bool has_interface (Grob*); - DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM )); static void add_column (Grob*, Grob*col); static void add_bar (Grob*me, Item*bar); diff --git a/lily/local-key-item.cc b/lily/local-key-item.cc index 15c2e9ec28..1014a232e7 100644 --- a/lily/local-key-item.cc +++ b/lily/local-key-item.cc @@ -17,21 +17,6 @@ #include "tie.hh" #include "lookup.hh" -static SCM -pitch_less (SCM p1, SCM p2) -{ - return Pitch::less_p (ly_car (p1), ly_car (p2)); -} - -static SCM pitch_less_proc; - -void -init_pitch_funcs () -{ - pitch_less_proc = gh_new_procedure2_0 ("pitch-less", &pitch_less); -} - -ADD_SCM_INIT_FUNC (lkpitch,init_pitch_funcs); void @@ -172,7 +157,6 @@ Local_key_item::brew_molecule (SCM smob) oct_b = true; } - lastoct = p.octave_i () ; bool cautionary = (scm_memq (ly_symbol2scm ("cautionary"), opts) != SCM_BOOL_F); @@ -181,7 +165,6 @@ Local_key_item::brew_molecule (SCM smob) int frs = (gh_exact_p(font_rel_siz) ? gh_scm2int(font_rel_siz) : 0); int cs = (gh_exact_p(caut_siz) ? gh_scm2int(caut_siz) : 0); - // Ugh. This will only work if only called once on each grob. --rz if (cautionary && caut_siz!=0) me->set_grob_property ("font-relative-size",gh_int2scm(frs+cs)); diff --git a/lily/new-accidental-engraver.cc b/lily/new-accidental-engraver.cc new file mode 100644 index 0000000000..a8918d089f --- /dev/null +++ b/lily/new-accidental-engraver.cc @@ -0,0 +1,466 @@ +/* + accidental-engraver.cc -- implement accidental_engraver + + (c) 1997--2002 Han-Wen Nienhuys + Modified 2001-2002 by Rune Zedeler +*/ + +#include "musical-request.hh" +#include "command-request.hh" +#include "local-key-item.hh" +#include "item.hh" +#include "tie.hh" +#include "rhythmic-head.hh" +#include "engraver-group-engraver.hh" +#include "accidental-placement.hh" +#include "side-position-interface.hh" +#include "engraver.hh" +#include "arpeggio.hh" +#include "warn.hh" + +#include "translator-group.hh" + +/** + + +FIXME: should not compute vertical positioning of accidentals, but +get them from the noteheads + +The algorithm for accidentals should be documented, and made +tweakable. + +*/ + +struct Accidental_entry { + bool done_; + Note_req * melodic_; + Grob * accidental_; + Translator_group *origin_; + Grob* head_; + Accidental_entry(); +}; + +Accidental_entry::Accidental_entry() +{ + done_ = false; + melodic_ =0; + accidental_ = 0; + origin_ = 0; + head_ = 0; +} + +struct New_accidental_engraver : Engraver { +protected: + TRANSLATOR_DECLARATIONS (New_accidental_engraver); + virtual void process_music (); + virtual void acknowledge_grob (Grob_info); + virtual void stop_translation_timestep (); + virtual void initialize (); + virtual void create_grobs (); + virtual void finalize (); +public: + + /* + TODO -> property. + + This is not a property, and it is not protected. This poses a + very small risk of the value being GC'd from under us. + + Oh well. + */ + SCM last_keysig_; + + /* + Urgh. Since the accidentals depend on lots of variables, we have to + store all information before we can really create the accidentals. + */ + Link_array arpeggios_; + + Grob * accidental_placement_; + + + /* + The next + */ + Array accidental_arr_; + + Link_array tie_arr_; + + +}; + + +New_accidental_engraver::New_accidental_engraver () +{ + accidental_placement_ = 0; + last_keysig_ = SCM_EOL; +} + +void +New_accidental_engraver::initialize () +{ + last_keysig_ = get_property ("keySignature"); + + Translator_group * trans_ = daddy_trans_l_; + while (trans_) + { + trans_ -> set_property ("localKeySignature", ly_deep_copy (last_keysig_)); + trans_ = trans_->daddy_trans_l_; + } + daddy_trans_l_->set_children_property ("localKeySignature", last_keysig_); +} + +/* + +calculates the number of accidentals on basis of the current local key sig + (passed as argument) + Returns number of accidentals (0, 1 or 2). + Negative (-1 or -2) if accidental has changed. + +*/ +static int +number_accidentals (SCM sig, Note_req * note_l, Pitch *pitch, SCM curbarnum, SCM lazyness, + bool ignore_octave_b) +{ + int n = pitch->notename_i_; + int o = pitch->octave_i_; + int a = pitch->alteration_i_; + int curbarnum_i = gh_scm2int (curbarnum); + int accbarnum_i = 0; + + SCM prev; + if (ignore_octave_b) + prev = ly_assoc_cdr (gh_int2scm (n), sig); + else + prev = gh_assoc (gh_cons (gh_int2scm (o), gh_int2scm (n)), sig); + + /* should really be true unless prev == SCM_BOOL_F */ + if (gh_pair_p (prev) && gh_pair_p (ly_cdr (prev))) + { + accbarnum_i = gh_scm2int (ly_cddr (prev)); + prev = gh_cons (ly_car (prev), ly_cadr (prev)); + } + + /* If an accidental was not found or the accidental was too old */ + if (prev == SCM_BOOL_F || + (gh_number_p (lazyness) && curbarnum_i > accbarnum_i + gh_scm2int (lazyness))) + prev = gh_assoc (gh_int2scm (n), sig); + + + SCM prev_acc = (prev == SCM_BOOL_F) ? gh_int2scm (0) : ly_cdr (prev); + + int p = gh_number_p (prev_acc) ? gh_scm2int (prev_acc) : 0; + + int num; + if (a == p + && !to_boolean (note_l->get_mus_property ("force-accidental")) + && gh_number_p (prev_acc)) + num = 0; + else if ( (abs (a)get_property ("localKeySignature"); + + bool same_octave_b = + gh_eq_p (ly_symbol2scm ("same-octave"), type); + bool any_octave_b = + gh_eq_p (ly_symbol2scm ("any-octave"), type); + + if (same_octave_b || any_octave_b) + { + int n = number_accidentals + (localsig, note_l, pitch, curbarnum, lazyness, any_octave_b); + diff = diff || (n < 0); + number = max (number, abs (n)); + } + else + warning (_f ("unknown accidental typesetting: %s. Ignored", + ly_symbol2string (type).ch_C ())); + } + + + /* + if symbol then it is a context name. Scan parent contexts to find it. + */ + else if (gh_symbol_p (ly_car (accidentals))) + { + String context = ly_symbol2string (ly_car (accidentals)); + + while (origin_l && !origin_l->is_alias_b (context)) + origin_l = origin_l->daddy_trans_l_; + + if (!origin_l) + warning (_f ("Symbol is not a parent context: %s. Ignored", + context.ch_C ())); + } + else warning (_f ("Accidental typesetting must be pair or context-name: %s", + ly_scm2string (ly_car (accidentals)).ch_C ())); + + accidentals = ly_cdr (accidentals); + } + return diff ? -number : number; +} + +void +New_accidental_engraver::create_grobs () +{ + if (accidental_arr_.size () && !accidental_arr_.top().done_) + { + //SCM localsig = get_property ("localKeySignature"); + SCM accidentals = get_property ("autoAccidentals"); + SCM cautionaries = get_property ("autoCautionaries"); + SCM barnum = get_property ("currentBarNumber"); + + bool extra_natural_b = get_property ("extraNatural") == SCM_BOOL_T; + for (int i = 0; i < accidental_arr_.size (); i++) + { + if (accidental_arr_[i].done_ ) + continue; + accidental_arr_[i].done_ = true; + Grob * support_l = accidental_arr_[i].head_; + Note_req * note_l = accidental_arr_[i].melodic_; + Translator_group * origin_l = accidental_arr_[i].origin_; + + Pitch * pitch = unsmob_pitch (note_l->get_mus_property ("pitch")); + int num = number_accidentals (note_l, pitch, origin_l, accidentals, barnum); + int num_caut = number_accidentals (note_l, pitch, origin_l, cautionaries, barnum); + bool cautionary = to_boolean (note_l->get_mus_property ("cautionary")); + + if (abs (num_caut) > abs (num)) + { + num = num_caut; + cautionary = true; + } + + bool different = num < 0; + num = abs (num); + + /* see if there's a tie that "changes" the accidental */ + /* works because if there's a tie, the note to the left + is of the same pitch as the actual note */ + + Grob *tie_break_reminder = 0; + bool tie_changes = false; + for (int j = 0; j < tie_arr_.size (); j++) + if (support_l == Tie::head (tie_arr_[j], RIGHT)) + { + tie_changes = different; + + /* Enable accidentals for broken tie + + We only want an accidental on a broken tie, + if the tie changes the accidental. + + Maybe check property noTieBreakForceAccidental? */ + if (different) + tie_break_reminder = tie_arr_[j]; + break; + } + + if (num) + { + Grob * a = new Item (get_property ("Accidental")); + a->set_parent (support_l, Y_AXIS); + + if (!accidental_placement_) + { + accidental_placement_ = new Item (get_property ("AccidentalPlacement")); + announce_grob (accidental_placement_, a->self_scm()); + } + + Accidental_placement::add_accidental (accidental_placement_, a); + + Side_position_interface::add_support (a, support_l); + announce_grob (a, SCM_EOL); + + // todo: add cautionary option + SCM accs = gh_cons (gh_int2scm (pitch->alteration_i_), SCM_EOL); + if (num == 2 && extra_natural_b) + accs = gh_cons (gh_int2scm (0), accs); + + if (tie_break_reminder) + ; // TODO. + support_l->set_grob_property ("accidentals-grob", a->self_scm ()); + + a->set_grob_property ("accidentals", accs); + accidental_arr_[i].accidental_ = a; + /* + 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], a); + } + + + /* + We should not record the accidental if it is the first + note and it is tied from the previous measure. + + Checking whether it is tied also works mostly, but will it + always do the correct thing? + */ + + + int n = pitch->notename_i_; + int o = pitch->octave_i_; + int a = pitch->alteration_i_; + SCM on_s = gh_cons (gh_int2scm (o), gh_int2scm (n)); + + /* + TODO: Speed this up! + + Perhaps only check translators mentioned in the auto-accidentals? + -rz + + TODO: profile this. + + I'd be surprised if the impact of this would be + measurable. Anyway, it seems localsig doesn't change + every time-step, but a set_property() is done every + time. We could save on that, probably. + + --hwn. + + + */ + + while (origin_l) + { + SCM localsig = origin_l->get_property ("localKeySignature"); + if (tie_changes) + { + /* + Remember an alteration that is different both from + that of the tied note and of the key signature. + */ + localsig = ly_assoc_front_x + (localsig, on_s, gh_cons (SCM_BOOL_T, barnum)); + } + else + { + /* + not really really correct if there are more than one + noteheads with the same notename. + */ + localsig = ly_assoc_front_x + (localsig, on_s, gh_cons (gh_int2scm (a), barnum)); + } + origin_l->set_property ("localKeySignature", localsig); + origin_l = origin_l->daddy_trans_l_; + } + } + } +} + +void +New_accidental_engraver::finalize () +{ + +} + +void +New_accidental_engraver::stop_translation_timestep () +{ + for (int i = 0; i < accidental_arr_.size(); i++) + { + Grob *a = accidental_arr_[i].accidental_; + if (a) + { + typeset_grob (a); + } + } + + if (accidental_placement_) + typeset_grob(accidental_placement_); + accidental_placement_ = 00; + + accidental_arr_.clear(); + arpeggios_.clear (); + tie_arr_.clear (); +} + +void +New_accidental_engraver::acknowledge_grob (Grob_info info) +{ + Note_req * note_l = dynamic_cast (info.music_cause ()); + + if (note_l && Rhythmic_head::has_interface (info.grob_l_)) + { + Accidental_entry entry ; + entry.head_ = info.grob_l_; + entry.origin_ = info.origin_trans_l_->daddy_trans_l_; + entry.melodic_ = note_l; + + accidental_arr_.push (entry); + } + else if (Tie::has_interface (info.grob_l_)) + { + tie_arr_.push (info.grob_l_); + } + else if (Arpeggio::has_interface (info.grob_l_)) + { + arpeggios_.push (info.grob_l_); + } + +} + +void +New_accidental_engraver::process_music () +{ + SCM sig = get_property ("keySignature"); + + /* Detect key sig changes. + Update all parents and children + */ + if (last_keysig_ != sig) + { + Translator_group * trans_ = daddy_trans_l_; + while (trans_) + { + trans_ -> set_property ("localKeySignature", ly_deep_copy (sig)); + trans_ = trans_->daddy_trans_l_; + } + daddy_trans_l_->set_children_property ("localKeySignature", sig); + + last_keysig_ = sig; + } +} + + + + + +ENTER_DESCRIPTION (New_accidental_engraver, +"Make accidentals. Catches note heads, ties and notices key-change +events. Due to interaction with ties (which don't come together +with note heads), this needs to be in a context higher than Tie_engraver.", + + "Accidental", + "rhythmic-head-interface tie-interface arpeggio-interface", + "localKeySignature extraNatural autoAccidentals autoCautionaries", + "localKeySignature"); diff --git a/lily/pitch.cc b/lily/pitch.cc index f5fe945f99..8bcfcb4e3a 100644 --- a/lily/pitch.cc +++ b/lily/pitch.cc @@ -348,6 +348,13 @@ pitch_semitones (SCM pp) return gh_int2scm (q); } +SCM pitch_less_proc; +static SCM +pitch_less (SCM p1, SCM p2) +{ + return Pitch::less_p (ly_car (p1), ly_car (p2)); +} + static void add_funcs () @@ -359,6 +366,7 @@ add_funcs () scm_c_define_gsubr ("pitch-alteration", 1, 0, 0, (Scheme_function_unknown)pitch_alteration); scm_c_define_gsubr ("pitch-semitones", 1, 0, 0, (Scheme_function_unknown)pitch_semitones); scm_c_define_gsubr ("Pitch::transpose", 2, 0, 0, (Scheme_function_unknown) pitch_transpose); + pitch_less_proc = gh_new_procedure2_0 ("pitch-less", &pitch_less); } ADD_SCM_INIT_FUNC (pitch, add_funcs); @@ -387,3 +395,4 @@ Pitch::alteration_i () const { return alteration_i_; } + diff --git a/lily/skyline.cc b/lily/skyline.cc new file mode 100644 index 0000000000..d010bf41c1 --- /dev/null +++ b/lily/skyline.cc @@ -0,0 +1,116 @@ +/* + skyline.cc -- implement Skyline_entry and funcs. + + source file of the GNU LilyPond music typesetter + + (c) 2002 Han-Wen Nienhuys +*/ + +#include "skyline.hh" + +void +insert_extent_into_skyline (Array *line, Box b, Axis line_axis, + Direction d) +{ + Interval extent = b[line_axis]; + if (extent.empty_b()) + return; + + Real stick_out = b[other_axis (line_axis)][d]; + + for (int i = line->size(); i--;) + { + Interval w = line->elem(i).width_; + if (extent[LEFT] > w[RIGHT]) + break; + + w.intersect (extent); + Real my_height = line->elem(i).height_; + + if (!w.empty_b () && d* (my_height - stick_out) < 0) + { + Interval e1 (line->elem(i).width_[LEFT], extent[LEFT]); + Interval e3 (extent[RIGHT], line->elem(i).width_[RIGHT]); + + if (!e3.empty_b ()) + line->insert (Skyline_entry (e3, my_height), i+1); + + line->elem_ref(i).height_ = stick_out; + line->elem_ref(i).width_ = w; + if (!e1.empty_b ()) + line->insert (Skyline_entry (e1, my_height), i ); + } + + + } +} + +Array +extents_to_skyline (Array extents, Axis a, Direction d) +{ + Array skyline; + + Interval i; + i.set_empty(); + i.swap(); + Skyline_entry e; + e.width_ = i; + e.height_ = -d * infinity_f; + skyline.push (e); + + /* + This makes a quadratic algorithm -- we could do better (n log (n) ) but that + seems overkill for now. + */ + for (int j = extents.size(); j--; ) + insert_extent_into_skyline (&skyline, extents[j], a, d); + + return skyline; +} + + +/* + minimum distance that can be achieved between baselines. "Clouds" is + a skyline pointing down. + */ +Real +skyline_meshing_distance (Array buildings, + Array clouds) +{ + int i = buildings.size () -1; + int j = clouds.size() -1; + + Real distance = - infinity_f; + + while (i > 0 || j > 0) + { + Interval w = buildings[i].width_; + w.intersect(clouds[j].width_); + + if (!w.empty_b()) + distance = distance >? (buildings[i].height_ - clouds[j].height_); + + if (i>0 && buildings[i].width_[LEFT] >= clouds[j].width_[LEFT]) + { + i--; + } + else if (j > 0 && buildings[i].width_[LEFT] <= clouds[j].width_[LEFT]) + { + j--; + } + } + + return distance; +} + +Skyline_entry::Skyline_entry() +{ + height_ = 0.0; +} + +Skyline_entry::Skyline_entry (Interval i, Real r) +{ + width_ = i; + height_ = r; + +} diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly index 60c6bd9725..4c75541b06 100644 --- a/ly/engraver-init.ly +++ b/ly/engraver-init.ly @@ -27,7 +27,7 @@ StaffContext=\translator { \consists "Staff_symbol_engraver" \consists "Collision_engraver" \consists "Rest_collision_engraver" - \consists "Accidental_engraver" + \consists "New_accidental_engraver" \consists "Piano_pedal_engraver" \consists "Instrument_name_engraver" \consists "Grob_pq_engraver" diff --git a/scm/grob-description.scm b/scm/grob-description.scm index 7bcdb1182f..9cb4c9dd54 100644 --- a/scm/grob-description.scm +++ b/scm/grob-description.scm @@ -26,6 +26,24 @@ (font-family . music) (meta . ((interfaces . (accidentals-interface staff-symbol-referencer-interface font-interface side-position-interface)))) )) + (Accidental + . ( + (molecule-callback . ,Accidental_interface::brew_molecule) + (X-offset-callbacks . (,Side_position_interface::aligned_side)) +; (after-line-breaking-callback . ,Local_key_item::after_line_breaking) + (direction . -1) + (left-padding . 0.2) + (right-padding . 0.5) + (paren-cautionaries . #t) + (font-family . music) + (meta . ((interfaces . (accidental-interface staff-symbol-referencer-interface font-interface side-position-interface)))) + )) + (AccidentalPlacement + . ( + (X-extent-callback . ,Axis_group_interface::group_extent_callback) +; (after-line-breaking-callback . ,Local_key_item::after_line_breaking) + (meta . ((interfaces . (accidental-placement-interface)))) + )) (Arpeggio . (