source file of the GNU LilyPond music typesetter
- (c) 1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+ (c) 1997--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
Jan Nieuwenhuizen <janneke@gnu.org>
*/
/*
[TODO]
- * remove *-hs variables, and do all y-position stuff in staff-space.
- This is not trivial, as Stem, and Stem_info both use point dimensions
- (indicated by _f suffix) in several places too.
-
- * shorter! (now +- 1000 lines)
- * less hairy code
- * move paper vars to scm
-
+ -* shorter! (now +- 1000 lines)
+
+ -* less hairy code
+
*/
void
Beam::add_stem (Grob*me, Grob*s)
{
- Pointer_group_interface:: add_element(me, "stems", s);
+ Pointer_group_interface:: add_element (me, "stems", s);
s->add_dependency (me);
[Alternatively, stems could set its own directions, according to
their beam, during 'final-pre-processing'.]
*/
-MAKE_SCHEME_CALLBACK(Beam,before_line_breaking,1);
+MAKE_SCHEME_CALLBACK (Beam,before_line_breaking,1);
SCM
Beam::before_line_breaking (SCM smob)
{
count[d] ++;
}
- } while (flip(&d) != DOWN);
+ } while (flip (&d) != DOWN);
SCM func = me->get_grob_property ("dir-function");
SCM s = gh_call2 (func,
/*
If dir is not determined: get default
*/
- return to_dir (me->get_grob_property ("default-neutral-direction"));
+ return to_dir (me->get_grob_property ("neutral-direction"));
}
Beam::set_stem_directions (Grob*me)
{
Link_array<Item> stems
- =Pointer_group_interface__extract_elements (me, (Item*) 0, "stems");
+ =Pointer_group_interface__extract_elements (me, (Item*) 0, "stems");
Direction d = Directional_element_interface::get (me);
for (int i=0; i <stems.size (); i++)
grob-properties y, dy.
User may set grob-properties: y-position-hs and height-hs
- (to be fixed) that override the calculated y and dy.
+ (to be fixed) that override the calculated y and dy.
Because y and dy cannot be calculated and quanted separately, we
always calculate both, then check for user override.
me->set_grob_property ("dy", gh_double2scm (0));
/* Hmm, callbacks should be called by, a eh, callback mechanism
- somewhere(?), I guess, not by looping here. */
+ somewhere (?), I guess, not by looping here. */
SCM list = me->get_grob_property ("y-dy-callbacks");
for (SCM i = list; gh_pair_p (i); i = gh_cdr (i))
Real y = 0;
Real dy = 0;
+ /* Stem_info, and thus y,dy in this function are corrected for beam-dir */
Real first_ideal = Stem::calc_stem_info (first_visible_stem (me)).idealy_f_;
if (first_ideal == Stem::calc_stem_info (last_visible_stem (me)).idealy_f_)
{
dy = dydx * dx;
}
- me->set_grob_property ("y", gh_double2scm (y));
- me->set_grob_property ("dy", gh_double2scm (dy));
+ /* Store true, not dir-corrected values */
+ Direction dir = Directional_element_interface::get (me);
+ me->set_grob_property ("y", gh_double2scm (y * dir));
+ me->set_grob_property ("dy", gh_double2scm (dy * dir));
return SCM_UNSPECIFIED;
}
if (visible_stem_count (me) <= 1)
return SCM_UNSPECIFIED;
- Real y = gh_scm2double (me->get_grob_property ("y"));
- Real dy = gh_scm2double (me->get_grob_property ("dy"));
-
+ /* Stem_info, and thus y,dy in this function are corrected for beam-dir */
+ Direction dir = Directional_element_interface::get (me);
+ Real y = gh_scm2double (me->get_grob_property ("y")) * dir;
+ Real dy = gh_scm2double (me->get_grob_property ("dy")) * dir;
+
/* steep slope running against lengthened stem is suspect */
Real first_ideal = Stem::calc_stem_info (first_visible_stem (me)).idealy_f_;
Real last_ideal = Stem::calc_stem_info (last_visible_stem (me)).idealy_f_;
Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - first_visible_stem (me)->relative_coordinate (0, X_AXIS);
Real dydx = dy && dx ? dy/dx : 0;
- if (((y - first_ideal > lengthened) && (dydx > steep))
+ if (( (y - first_ideal > lengthened) && (dydx > steep))
|| ((y + dy - last_ideal > lengthened) && (dydx < -steep)))
{
Real adjusted_y = y + dy / 2;
- me->set_grob_property ("y", gh_double2scm (adjusted_y));
+ /* Store true, not dir-corrected values */
+ me->set_grob_property ("y", gh_double2scm (adjusted_y * dir));
me->set_grob_property ("dy", gh_double2scm (0));
}
return SCM_UNSPECIFIED;
if (damping)
{
- Real y = gh_scm2double (me->get_grob_property ("y"));
- Real dy = gh_scm2double (me->get_grob_property ("dy"));
+ /* y,dy in this function are corrected for beam-dir */
+ Direction dir = Directional_element_interface::get (me);
+ Real y = gh_scm2double (me->get_grob_property ("y")) * dir;
+ Real dy = gh_scm2double (me->get_grob_property ("dy")) * dir;
// ugh -> use commonx
Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS)
Real damped_dy = dydx * dx;
Real adjusted_y = y + (dy - damped_dy) / 2;
- me->set_grob_property ("y", gh_double2scm (adjusted_y));
- me->set_grob_property ("dy", gh_double2scm (damped_dy));
+ /* Store true, not dir-corrected values */
+ me->set_grob_property ("y", gh_double2scm (adjusted_y * dir));
+ me->set_grob_property ("dy", gh_double2scm (damped_dy * dir));
}
return SCM_UNSPECIFIED;
}
if (a.size () > 1)
{
- Real y = gh_scm2double (me->get_grob_property ("y"));
- Real dy = gh_scm2double (me->get_grob_property ("dy"));
+ /* y,dy in this function are corrected for beam-dir */
+ Direction dir = Directional_element_interface::get (me);
+ Real y = gh_scm2double (me->get_grob_property ("y")) * dir;
+ Real dy = gh_scm2double (me->get_grob_property ("dy")) * dir;
Real staff_space = Staff_symbol_referencer::staff_space (me);
Real quantised_dy = q * sign (dy);
Real adjusted_y = y + (dy - quantised_dy) / 2;
- me->set_grob_property ("y", gh_double2scm (adjusted_y));
- me->set_grob_property ("dy", gh_double2scm (quantised_dy));
+ /* Store true, not dir-corrected values */
+ me->set_grob_property ("y", gh_double2scm (adjusted_y * dir));
+ me->set_grob_property ("dy", gh_double2scm (quantised_dy * dir));
}
return SCM_UNSPECIFIED;
}
-
-/*
- What to do? Why do we have two dimensions (staff-position and
- staff-space)? Do other grobs export staff-position to the user,
- should we junk that?
-
- height-hs -> staff-position-height
- y-position-hs -> staff-position
-
- or
-
- height-hs -> height / 2
- y-postion-hs -> y-position / 2
-
-
- UGHUGH. IF this callback is omitted, we hang.
- FIXME: until here, we used only stem_info, which acts as if dir=up.
-*/
+/* It's tricky to have the user override y,dy directly, so we use this
+ translation func. Also, if our staff_space != 1 (smaller staff, eg),
+ user will expect staff-position to be discrete values. */
MAKE_SCHEME_CALLBACK (Beam, user_override, 1);
SCM
Beam::user_override (SCM smob)
{
Grob *me = unsmob_grob (smob);
- Real half_space = Staff_symbol_referencer::staff_space (me) / 2;
-
- Real y = gh_scm2double (me->get_grob_property ("y"));
- Real dy = gh_scm2double (me->get_grob_property ("dy"));
+ Real staff_space = Staff_symbol_referencer::staff_space (me);
-
- SCM s = me->get_grob_property ("y-position-hs");
+ SCM s = me->get_grob_property ("staff-position");
if (gh_number_p (s))
- y = gh_scm2double (s) * half_space;
- else
- // ughugh
- y *= Directional_element_interface::get (me);
+ {
+ Real y = gh_scm2double (s) * staff_space * 0.5;
+ me->set_grob_property ("y", gh_double2scm (y));
+ }
- s = me->get_grob_property ("height-hs");
+ /* Name suggestions? Tilt, slope, vertical-* ? */
+ s = me->get_grob_property ("height");
if (gh_number_p (s))
- dy = gh_scm2double (s) * half_space;
- else
- // ughugh
- dy *= Directional_element_interface::get (me);
-
-
- me->set_grob_property ("y", gh_double2scm (y));
- me->set_grob_property ("dy", gh_double2scm (dy));
+ {
+ Real dy = gh_scm2double (s) * staff_space * 0.5;
+ me->set_grob_property ("dy", gh_double2scm (dy));
+ }
return SCM_UNSPECIFIED;
}
Link_array<Item> stems=
Pointer_group_interface__extract_elements (me, (Item*)0, "stems");
- for (int i=0; i < stems.size(); i++)
+ for (int i=0; i < stems.size (); i++)
{
Item* s = stems[i];
if (Stem::invisible_b (s))
Real stem_y = calc_stem_y_f (me, s, y, dy);
+ // doesn't play well with dvips
+ if (scm_definedp (ly_symbol2scm ("ps-testing"), SCM_UNDEFINED)
+ == SCM_BOOL_T)
+ if (Stem::get_direction (s) == Directional_element_interface::get (me))
+ stem_y += Stem::get_direction (s)
+ * gh_scm2double (me->get_grob_property ("thickness")) / 2;
+
/* caution: stem measures in staff-positions */
Real id = me->relative_coordinate (common, Y_AXIS)
- stems[i]->relative_coordinate (common, Y_AXIS);
Real q = up_y - iv[SMALLER] <= iv[BIGGER] - up_y
? iv[SMALLER] : iv[BIGGER];
if (quant_dir)
- q = iv[(Direction)quant_dir];
+ q = iv[ (Direction)quant_dir];
return q * Directional_element_interface::get (me);
}
Pointer_group_interface__extract_elements (me, (Grob*)0, "stems");
Direction d = LEFT;
- for (int i=0; i < stems.size(); i++)
+ for (int i=0; i < stems.size (); i++)
{
do
{
FIXME: clean me up.
*/
Molecule
-Beam::stem_beams (Grob*me,Item *here, Item *next, Item *prev)
+Beam::stem_beams (Grob*me,Item *here, Item *next, Item *prev,
+ Real dy, Real dydx
+ )
{
// ugh -> use commonx
- if ((next && !(next->relative_coordinate (0, X_AXIS) > here->relative_coordinate (0, X_AXIS))) ||
- (prev && !(prev->relative_coordinate (0, X_AXIS) < here->relative_coordinate (0, X_AXIS))))
+ if ((next && ! (next->relative_coordinate (0, X_AXIS) > here->relative_coordinate (0, X_AXIS))) ||
+ (prev && ! (prev->relative_coordinate (0, X_AXIS) < here->relative_coordinate (0, X_AXIS))))
programming_error ("Beams are not left-to-right");
- Real staffline_f = me->paper_l ()->get_var ("stafflinethickness");
int multiplicity = get_multiplicity (me);
SCM space_proc = me->get_grob_property ("space-function");
Real interbeam_f = gh_scm2double (space) ;
Real bdy = interbeam_f;
- Real stemdx = staffline_f;
-
+
+#if 0
// ugh -> use commonx
Real dx = visible_stem_count (me) ?
last_visible_stem (me)->relative_coordinate (0, X_AXIS) - first_visible_stem (me)->relative_coordinate (0, X_AXIS)
: 0.0;
- Real dy = gh_scm2double (me->get_grob_property ("dy"));
- Real dydx = dy && dx ? dy/dx : 0;
-
+#endif
+
Molecule leftbeams;
Molecule rightbeams;
Direction dir = Directional_element_interface::get (me);
+ /* [Tremolo] beams on whole notes may not have direction set? */
+ if (dir == CENTER)
+ dir = Directional_element_interface::get (here);
+
/* half beams extending to the left. */
if (prev)
{
Half beam should be one note-width,
but let's make sure two half-beams never touch
*/
- Real w = here->relative_coordinate (0, X_AXIS) - prev->relative_coordinate (0, X_AXIS);
+
+ // FIXME: TODO (check) stem width / sloped beams
+ Real w = here->relative_coordinate (0, X_AXIS)
+ - prev->relative_coordinate (0, X_AXIS);
+ Real stem_w = gh_scm2double (prev->get_grob_property ("thickness"))
+ // URG
+ * me->paper_l ()->get_var ("stafflinethickness");
+
w = w/2 <? nw_f;
Molecule a;
if (lhalfs) // generates warnings if not
- a = Lookup::beam (dydx, w, thick);
+ a = Lookup::beam (dydx, w + stem_w, thick);
a.translate (Offset (-w, -w * dydx));
+ a.translate_axis (-stem_w/2, X_AXIS);
for (int j = 0; j < lhalfs; j++)
{
Molecule b (a);
if (next)
{
- int rhalfs = Stem::beam_count (here,RIGHT) - Stem::beam_count (next,LEFT);
- int rwholebeams= Stem::beam_count (here,RIGHT) <? Stem::beam_count (next,LEFT) ;
+ int rhalfs = Stem::beam_count (here,RIGHT)
+ - Stem::beam_count (next,LEFT);
+ int rwholebeams= Stem::beam_count (here,RIGHT)
+ <? Stem::beam_count (next,LEFT) ;
- Real w = next->relative_coordinate (0, X_AXIS) - here->relative_coordinate (0, X_AXIS);
- Molecule a = Lookup::beam (dydx, w + stemdx, thick);
- a.translate_axis( - stemdx/2, X_AXIS);
+ Real w = next->relative_coordinate (0, X_AXIS)
+ - here->relative_coordinate (0, X_AXIS);
+
+ Real stem_w = gh_scm2double (next->get_grob_property ("thickness"))
+ // URG
+ * me->paper_l ()->get_var ("stafflinethickness");
+
+ Molecule a = Lookup::beam (dydx, w + stem_w, thick);
+ a.translate_axis (- stem_w/2, X_AXIS);
int j = 0;
Real gap_f = 0;
-
+
SCM gap = me->get_grob_property ("gap");
if (gh_number_p (gap))
{
- int gap_i = gh_scm2int ( (gap));
+ int gap_i = gh_scm2int ((gap));
int nogap = rwholebeams - gap_i;
for (; j < nogap; j++)
b.translate_axis (-dir * bdy * j, Y_AXIS);
rightbeams.add_molecule (b);
}
- // TODO: notehead widths differ for different types
- gap_f = nw_f / 2;
+ if (Stem::invisible_b (here))
+ gap_f = nw_f;
+ else
+ gap_f = nw_f / 2;
w -= 2 * gap_f;
- a = Lookup::beam (dydx, w + stemdx, thick);
+ a = Lookup::beam (dydx, w + stem_w, thick);
}
for (; j < rwholebeams; j++)
{
Molecule b (a);
- b.translate (Offset (Stem::invisible_b (here) ? 0 : gap_f, -dir * bdy * j));
+ Real tx = 0;
+ if (Stem::invisible_b (here))
+ // ugh, see chord-tremolo.ly
+ tx = (-dir + 1) / 2 * nw_f * 1.5 + gap_f/4;
+ else
+ tx = gap_f;
+ b.translate (Offset (tx, -dir * bdy * j));
rightbeams.add_molecule (b);
}
return leftbeams;
}
-MAKE_SCHEME_CALLBACK(Beam,brew_molecule,1);
+MAKE_SCHEME_CALLBACK (Beam,brew_molecule,1);
SCM
Beam::brew_molecule (SCM smob)
{
else
{
x0 = stems[0]->relative_coordinate (0, X_AXIS);
- dx = stems.top()->relative_coordinate (0, X_AXIS) - x0;
+ dx = stems.top ()->relative_coordinate (0, X_AXIS) - x0;
}
+
+
+ /*
+ TODO: the naming of the grob properties sucks.
+ */
+ SCM dy_s = me->get_grob_property ("dy");
+ SCM y_s = me->get_grob_property ("y");
+
- Real dy = gh_scm2double (me->get_grob_property ("dy"));
+ Real dy = gh_number_p (dy_s) ? gh_scm2double (dy_s) : 0.0;
Real dydx = dy && dx ? dy/dx : 0;
- Real y = gh_scm2double (me->get_grob_property ("y"));
+ Real y = gh_number_p (y_s) ? gh_scm2double (y_s) : 0.0;
- for (int j=0; j <stems.size (); j++)
+ for (int j=0; j <stems.size (); j++)
{
Item *i = stems[j];
Item * prev = (j > 0)? stems[j-1] : 0;
- Item * next = (j < stems.size()-1) ? stems[j+1] :0;
+ Item * next = (j < stems.size ()-1) ? stems[j+1] :0;
- Molecule sb = stem_beams (me, i, next, prev);
+ Molecule sb = stem_beams (me, i, next, prev, dy, dydx);
Real x = i->relative_coordinate (0, X_AXIS)-x0;
sb.translate (Offset (x, x * dydx + y));
mol.add_molecule (sb);
Beam::forced_stem_count (Grob*me)
{
Link_array<Item>stems =
- Pointer_group_interface__extract_elements ( me, (Item*) 0, "stems");
+ Pointer_group_interface__extract_elements (me, (Item*) 0, "stems");
int f = 0;
for (int i=0; i < stems.size (); i++)
{
if (Stem::invisible_b (s))
continue;
- if (((int)Stem::chord_start_f (s))
- && (Stem::get_direction (s ) != Stem::get_default_dir (s )))
+ if (( (int)Stem::chord_start_f (s))
+ && (Stem::get_direction (s) != Stem::get_default_dir (s)))
f++;
}
return f;
}
Item*
-Beam::first_visible_stem(Grob*me)
+Beam::first_visible_stem (Grob*me)
{
Link_array<Item>stems =
- Pointer_group_interface__extract_elements ( me, (Item*) 0, "stems");
+ Pointer_group_interface__extract_elements (me, (Item*) 0, "stems");
for (int i = 0; i < stems.size (); i++)
{
}
Item*
-Beam::last_visible_stem(Grob*me)
+Beam::last_visible_stem (Grob*me)
{
Link_array<Item>stems =
- Pointer_group_interface__extract_elements ( me, (Item*) 0, "stems");
+ Pointer_group_interface__extract_elements (me, (Item*) 0, "stems");
for (int i = stems.size (); i--;)
{
if (!Stem::invisible_b (stems[i]))
rest -> stem -> beam -> interpolate_y_position ()
*/
-MAKE_SCHEME_CALLBACK(Beam,rest_collision_callback,2);
+MAKE_SCHEME_CALLBACK (Beam,rest_collision_callback,2);
SCM
Beam::rest_collision_callback (SCM element_smob, SCM axis)
{
beam_y = gh_scm2double (s);
// ugh -> use commonx
- Real x0 = first_visible_stem(beam)->relative_coordinate (0, X_AXIS);
- Real dx = last_visible_stem(beam)->relative_coordinate (0, X_AXIS) - x0;
+ Real x0 = first_visible_stem (beam)->relative_coordinate (0, X_AXIS);
+ Real dx = last_visible_stem (beam)->relative_coordinate (0, X_AXIS) - x0;
Real dydx = beam_dy && dx ? beam_dy/dx : 0;
Direction d = Stem::get_direction (stem);
if (discrete_dist < stafflines+1)
discrete_dist = int (ceil (discrete_dist / 2.0)* 2.0);
- return gh_double2scm (-d * discrete_dist);
+ return gh_double2scm (-d * discrete_dist);
}
return me->has_interface (ly_symbol2scm ("beam-interface"));
}
-void
-Beam::set_interface (Grob*me)
-{
-#if 0
- /*
- why the init? No way to tell difference between default and user
- override. */
- me->set_grob_property ("y" ,gh_double2scm (0));
- me->set_grob_property ("dy", gh_double2scm (0));
- me->set_interface (ly_symbol2scm("beam-interface"));
-#endif
-}