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.
2003-09-15 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+ * 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.
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 */
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;
}
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 ());
}
}
}
- tremolo_req_ = 0;
+ tremolo_ev_ = 0;
}
bool
{
if (r->is_mus_type ("tremolo-event"))
{
- tremolo_req_ = r;
+ tremolo_ev_ = r;
return true;
}
return false;
}
-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;
// 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;
programming_error ("No tremolo flags?");
me->suicide();
- return SCM_EOL;
+ return Molecule ();
}
/*
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.
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
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
{
#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)
ps.push (p);
}
-
+
ps.sort (icmp);
return ps;
}
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<Real> 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))
{
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
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;
*/
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
{
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,
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
return si;
}
+
+/*
+ TODO: add extra space for tremolos!
+ */
void
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;
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