From c7ad234892957a5b171cba438372fa90325f09f5 Mon Sep 17 00:00:00 2001 From: hanwen Date: Mon, 15 Sep 2003 21:35:08 +0000 Subject: [PATCH] * lily/stem.cc (get_default_stem_end_position): lengthen stems for tremoloed stems. * lily/stem-tremolo.cc (brew_molecule): position tremolo next to head for flagged stems. * lily/stem.cc (get_default_stem_end_position): futz with extra stem length if there is a stem tremolo. --- ChangeLog | 9 ++++ lily/include/stem-tremolo.hh | 1 + lily/stem-engraver.cc | 37 ++++++------- lily/stem-tremolo.cc | 48 ++++++++++++----- lily/stem.cc | 95 ++++++++++++++++++++++++++-------- scm/define-grob-properties.scm | 1 + 6 files changed, 136 insertions(+), 55 deletions(-) diff --git a/ChangeLog b/ChangeLog index 898574255b..9526998150 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2003-09-15 Han-Wen Nienhuys + * lily/stem.cc (get_default_stem_end_position): lengthen stems for + tremoloed stems. + + * lily/stem-tremolo.cc (brew_molecule): position tremolo next to + head for flagged stems. + + * lily/stem.cc (get_default_stem_end_position): futz with extra + stem length if there is a stem tremolo. + * lily/tuplet-bracket.cc (brew_molecule): don't print bracket when it would be too small. diff --git a/lily/include/stem-tremolo.hh b/lily/include/stem-tremolo.hh index 6a54d95a39..d214822688 100644 --- a/lily/include/stem-tremolo.hh +++ b/lily/include/stem-tremolo.hh @@ -22,6 +22,7 @@ public: DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM )); DECLARE_SCHEME_CALLBACK (height, (SCM,SCM)); static void set_stem (Grob*me, Grob *st); + static Molecule raw_molecule (Grob*); }; #endif /* ABBREV_HH */ diff --git a/lily/stem-engraver.cc b/lily/stem-engraver.cc index 7535d39162..4c7946af05 100644 --- a/lily/stem-engraver.cc +++ b/lily/stem-engraver.cc @@ -32,16 +32,16 @@ protected: private: Grob *stem_; Grob *tremolo_; - Music *rhythmic_req_; - Music* tremolo_req_; + Music *rhythmic_ev_; + Music* tremolo_ev_; }; Stem_engraver::Stem_engraver () { - tremolo_req_ = 0; + tremolo_ev_ = 0; stem_ = 0; tremolo_ = 0; - rhythmic_req_ =0; + rhythmic_ev_ =0; } @@ -68,48 +68,49 @@ Stem_engraver::acknowledge_grob (Grob_info i) stem_->set_grob_property ("duration-log", gh_int2scm (duration_log)); - if (tremolo_req_) + if (tremolo_ev_) { /* Stem tremolo is never applied to a note by default, - is must me requested. But there is a default for the + is must me evuested. But there is a default for the tremolo value: c4:8 c c: the first and last (quarter) note bothe get one tremolo flag. */ - int requested_type = gh_scm2int (tremolo_req_->get_mus_property ("tremolo-type")); + int evuested_type = gh_scm2int (tremolo_ev_->get_mus_property ("tremolo-type")); SCM f = get_property ("tremoloFlags"); - if (!requested_type) + if (!evuested_type) if (gh_number_p (f)) - requested_type = gh_scm2int (f); + evuested_type = gh_scm2int (f); else - requested_type = 8; + evuested_type = 8; else - daddy_trans_->set_property ("tremoloFlags", gh_int2scm (requested_type)); + daddy_trans_->set_property ("tremoloFlags", gh_int2scm (evuested_type)); - int tremolo_flags = intlog2 (requested_type) - 2 + int tremolo_flags = intlog2 (evuested_type) - 2 - (duration_log > 2 ? duration_log - 2 : 0); if (tremolo_flags <= 0) { - tremolo_req_->origin()->warning (_("tremolo duration is too long")); + tremolo_ev_->origin()->warning (_("tremolo duration is too long")); tremolo_flags = 0; } if (tremolo_flags) { tremolo_ = new Item (get_property ("StemTremolo")); - announce_grob(tremolo_, tremolo_req_->self_scm()); + announce_grob(tremolo_, tremolo_ev_->self_scm()); /* The number of tremolo flags is the number of flags of the tremolo-type minus the number of flags of the note itself. */ - tremolo_->set_grob_property ("flag-count", - gh_int2scm (tremolo_flags)); + tremolo_->set_grob_property ("flag-count", + gh_int2scm (tremolo_flags)); tremolo_->set_parent (stem_, X_AXIS); + stem_->set_grob_property ("tremolo-flag", tremolo_->self_scm ()); } } @@ -160,7 +161,7 @@ Stem_engraver::stop_translation_timestep () } - tremolo_req_ = 0; + tremolo_ev_ = 0; } bool @@ -168,7 +169,7 @@ Stem_engraver::try_music (Music* r) { if (r->is_mus_type ("tremolo-event")) { - tremolo_req_ = r; + tremolo_ev_ = r; return true; } return false; diff --git a/lily/stem-tremolo.cc b/lily/stem-tremolo.cc index cac78d7e8a..dba612fc70 100644 --- a/lily/stem-tremolo.cc +++ b/lily/stem-tremolo.cc @@ -55,23 +55,22 @@ Stem_tremolo::height (SCM smob, SCM ax) } -MAKE_SCHEME_CALLBACK (Stem_tremolo,brew_molecule,1); -SCM -Stem_tremolo::brew_molecule (SCM smob) +Molecule +Stem_tremolo::raw_molecule (Grob *me) { - Grob *me= unsmob_grob (smob); - Grob * stem = unsmob_grob (me->get_grob_property ("stem")); - Grob * beam = Stem::get_beam (stem); + Grob *stem = unsmob_grob (me->get_grob_property ("stem")); + Grob *beam = Stem::get_beam (stem); Real dydx; if (beam) { Real dy = 0; SCM s = beam->get_grob_property ("positions"); - if (gh_pair_p (s)) + if (ly_number_pair_p (s)) { dy = -gh_scm2double (gh_car (s)) +gh_scm2double (gh_cdr (s)); } + Real dx = Beam::last_visible_stem (beam)->relative_coordinate (0, X_AXIS) - Beam::first_visible_stem (beam)->relative_coordinate (0, X_AXIS); dydx = dx ? dy/dx : 0; @@ -80,7 +79,7 @@ Stem_tremolo::brew_molecule (SCM smob) // urg dydx = 0.25; - Real ss = Staff_symbol_referencer::staff_space (stem); + Real ss = Staff_symbol_referencer::staff_space (me); Real thick = gh_scm2double (me->get_grob_property ("beam-thickness")); Real width = gh_scm2double (me->get_grob_property ("beam-width")); width *= ss; @@ -99,7 +98,7 @@ Stem_tremolo::brew_molecule (SCM smob) programming_error ("No tremolo flags?"); me->suicide(); - return SCM_EOL; + return Molecule (); } /* @@ -116,11 +115,26 @@ Stem_tremolo::brew_molecule (SCM smob) b.translate_axis (beam_translation * i, Y_AXIS); mol.add_molecule (b); } + return mol; +} + + +MAKE_SCHEME_CALLBACK (Stem_tremolo,brew_molecule,1); +SCM +Stem_tremolo::brew_molecule (SCM grob) +{ + Grob *me = unsmob_grob (grob); + Grob *stem = unsmob_grob (me->get_grob_property ("stem")); + Grob *beam = Stem::get_beam (stem); Direction stemdir = Stem::get_direction (stem); + Real beam_translation = beam ? Beam::get_beam_translation (beam) : 0.81; + + Molecule mol = raw_molecule (me); Interval mol_ext = mol.extent (Y_AXIS); + Real ss = Staff_symbol_referencer::staff_space (me); // ugh, rather calc from Stem_tremolo_req - int beams_i = (beam) ? (Stem::beam_multiplicity (stem).length ()+ 1): 0; + int beam_count = (beam) ? (Stem::beam_multiplicity (stem).length ()+ 1): 0; /* TODO. @@ -136,8 +150,8 @@ Stem_tremolo::brew_molecule (SCM smob) Real end_y = Stem::stem_end_position (stem) *ss/2 - - stemdir * (beams_i * beamthickness - + ((beams_i -1) >? 0) * beam_translation); + - stemdir * (beam_count * beamthickness + + ((beam_count -1) >? 0) * beam_translation); /* the 0.33 ss is to compensate for the size of the note head @@ -148,12 +162,18 @@ Stem_tremolo::brew_molecule (SCM smob) Real padding = beam_translation; /* + if there is a flag, just above/below the notehead. if there is not enough space, center on remaining space, else one beamspace away from stem end. */ - if (stemdir * (end_y - chord_start_y) - 2*padding - mol_ext.length () < 0.0) + if (!beam && Stem::duration_log (stem) >= 3) + { + mol.align_to (Y_AXIS, -stemdir); + mol.translate_axis (chord_start_y + .5 * stemdir, Y_AXIS); + } + else if (stemdir * (end_y - chord_start_y) - 2*padding - mol_ext.length () < 0.0) { - mol.translate_axis ((end_y + chord_start_y) /2.0 - mol_ext.center (),Y_AXIS); + mol.translate_axis (0.5 * (end_y + chord_start_y) - mol_ext.center (),Y_AXIS); } else { diff --git a/lily/stem.cc b/lily/stem.cc index f0f30ea685..45cd45ce21 100644 --- a/lily/stem.cc +++ b/lily/stem.cc @@ -33,6 +33,7 @@ #include "spanner.hh" #include "side-position-interface.hh" #include "dot-column.hh" +#include "stem-tremolo.hh" void Stem::set_beaming (Grob*me, int beam_count, Direction d) @@ -229,7 +230,7 @@ Stem::note_head_positions (Grob *me) ps.push (p); } - + ps.sort (icmp); return ps; } @@ -284,12 +285,16 @@ Stem::get_default_stem_end_position (Grob*me) Direction dir = get_direction (me); return dir * (line_count + 3.5); } - + Real ss = Staff_symbol_referencer::staff_space (me); + + int durlog = duration_log (me); + bool grace_b = to_boolean (me->get_grob_property ("grace")); SCM s; Array a; - Real length = 3.5; + + Real length = 7; // WARNING: IN HALF SPACES SCM scm_len = me->get_grob_property ("length"); if (gh_number_p (scm_len)) { @@ -300,20 +305,10 @@ Stem::get_default_stem_end_position (Grob*me) s = me->get_grob_property ("lengths"); if (gh_pair_p (s)) { - length = 2* gh_scm2double (robust_list_ref (duration_log(me) -2, s)); + length = 2* gh_scm2double (robust_list_ref (durlog -2, s)); } } - Real shorten = 0.0; - - SCM sshorten = me->get_grob_property ("stem-shorten"); - SCM scm_shorten = gh_pair_p (sshorten) ? - robust_list_ref ((duration_log (me) - 2) >? 0, sshorten): SCM_EOL; - if (gh_number_p (scm_shorten)) - { - shorten = 2* gh_scm2double (scm_shorten); - } - /* URGURGURG @@ -326,16 +321,65 @@ Stem::get_default_stem_end_position (Grob*me) Directional_element_interface::set (me, dir); } - /* On boundary: shorten only half */ - if (abs (head_positions (me)[get_direction (me)]) <= 1) - shorten *= 0.5; - + /* stems in unnatural (forced) direction should be shortened, according to [Roush & Gourlay] */ if (!chord_start_y (me) || (get_direction (me) != get_default_dir (me))) - length -= shorten; + { + + Real shorten = 0.0; + + SCM sshorten = me->get_grob_property ("stem-shorten"); + SCM scm_shorten = gh_pair_p (sshorten) ? + robust_list_ref ((duration_log (me) - 2) >? 0, sshorten): SCM_EOL; + if (gh_number_p (scm_shorten)) + { + shorten = 2* gh_scm2double (scm_shorten); + } + + /* On boundary: shorten only half */ + if (abs (head_positions (me)[get_direction (me)]) <= 1) + shorten *= 0.5; + + length -= shorten; + } + + /* + Tremolo stuff: + */ + Grob * trem = unsmob_grob (me->get_grob_property ("tremolo-flag")); + if (trem && !unsmob_grob (me->get_grob_property ("beam"))) + { + /* + Crude hack: add extra space if tremolo flag is there. + + We can't do this for the beam, since we get into a loop + (Stem_tremolo::raw_molecule() looks at the beam.) + + --hwn + */ + + Real minlen = + 1.0 + 2 * Stem_tremolo::raw_molecule (trem).extent (Y_AXIS).length () / ss; + + if (durlog >= 3) + { + Interval flag_ext = flag (me).extent (Y_AXIS) ; + if (!flag_ext.empty_b()) + minlen += 2 * flag_ext.length () / ss ; + /* + The clash is smaller for down stems (since the tremolo is + angled up.) + */ + if (dir == DOWN) + minlen -= 1.0; + } + + length = length >? (minlen + 1.0); + } + Interval hp = head_positions (me); Real st = hp[dir] + dir * length; @@ -353,7 +397,7 @@ Stem::get_default_stem_end_position (Grob*me) */ if (!get_beam (me) && dir == UP - && duration_log (me) > 2) + && durlog > 2) { Grob * closest_to_flag = extremal_heads (me)[dir]; Grob * dots = closest_to_flag @@ -363,7 +407,7 @@ Stem::get_default_stem_end_position (Grob*me) { Real dp = Staff_symbol_referencer::get_position (dots); Real flagy = flag (me).extent (Y_AXIS)[-dir] * 2 - / Staff_symbol_referencer::staff_space (me); + / ss; /* Very gory: add myself to the X-support of the parent, @@ -579,7 +623,8 @@ Stem::flag (Grob*me) flag's shape accordingly. In the worst case, the shape looks slightly misplaced, but that will usually be the programmer's fault (e.g. when trying to attach multiple - note heads to a single stem in mensural notation). */ + note heads to a single stem in mensural notation). + */ /* perhaps the detection whether this correction is needed should @@ -806,6 +851,10 @@ Stem::get_stem_info (Grob *me) return si; } + +/* + TODO: add extra space for tremolos! + */ void Stem::calc_stem_info (Grob *me) { @@ -921,7 +970,7 @@ Stem::calc_stem_info (Grob *me) /* stem only extends to center of beam */ - 0.5 * beam_thickness; - Real minimum_y = note_start + minimum_length; + Real minimum_y = note_start + minimum_length; ideal_y *= my_dir; diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index c7a821c437..6bcb585d53 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -447,6 +447,7 @@ notation manual for more information.") same as setting molecule-callback to #f, but this retains the dimensions of this grob, which means that you can erase grobs individually. .") +(grob-property-description 'tremolo-flag ly:grob? "The tremolo object on a stem.") (grob-property-description 'bracket-visibility boolean-or-symbol? " This controls the visibility of the tuplet bracket. Setting it to false will prevent printing of the -- 2.39.5