2 stem-tremolo.cc -- implement Stem_tremolo
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
10 #include "stem-tremolo.hh"
13 #include "paper-def.hh"
17 #include "staff-symbol-referencer.hh"
18 #include "directional-element-interface.hh"
22 lengthen stem if necessary
24 MAKE_SCHEME_CALLBACK (Stem_tremolo
,dim_callback
,2);
30 Stem_tremolo::dim_callback (SCM e
, SCM
)
32 Grob
* se
= unsmob_grob (e
);
34 Real space
= Staff_symbol_referencer::staff_space (se
);
35 return ly_interval2scm (Interval (-space
, space
));
41 MAKE_SCHEME_CALLBACK (Stem_tremolo
, height
, 2);
43 Stem_tremolo::height (SCM smob
, SCM ax
)
45 Axis a
= (Axis
)gh_scm2int (ax
);
46 Grob
* me
= unsmob_grob (smob
);
49 SCM mol
= me
->get_uncached_molecule ();
51 if (Molecule
*m
= unsmob_molecule (mol
))
52 return ly_interval2scm (m
->extent (a
));
54 return ly_interval2scm (Interval());
59 Stem_tremolo::raw_molecule (Grob
*me
)
61 Grob
*stem
= unsmob_grob (me
->get_grob_property ("stem"));
62 Grob
*beam
= Stem::get_beam (stem
);
68 SCM s
= beam
->get_grob_property ("positions");
69 if (is_number_pair (s
))
71 dy
= -gh_scm2double (gh_car (s
)) +gh_scm2double (gh_cdr (s
));
74 Real dx
= Beam::last_visible_stem (beam
)->relative_coordinate (0, X_AXIS
)
75 - Beam::first_visible_stem (beam
)->relative_coordinate (0, X_AXIS
);
76 dydx
= dx
? dy
/dx
: 0;
82 Real ss
= Staff_symbol_referencer::staff_space (me
);
83 Real thick
= gh_scm2double (me
->get_grob_property ("beam-thickness"));
84 Real width
= gh_scm2double (me
->get_grob_property ("beam-width"));
88 Molecule
a (Lookup::beam (dydx
, width
, thick
));
89 a
.translate (Offset (-width
/2, width
/ 2 * dydx
));
91 int tremolo_flags
= 0;
92 SCM s
= me
->get_grob_property ("flag-count");
94 tremolo_flags
= gh_scm2int (s
);
98 programming_error ("No tremolo flags?");
105 Who the fuck is 0.81 ?
109 Real beam_translation
= beam
? Beam::get_beam_translation (beam
) : 0.81;
112 for (int i
= 0; i
< tremolo_flags
; i
++)
115 b
.translate_axis (beam_translation
* i
, Y_AXIS
);
116 mol
.add_molecule (b
);
122 MAKE_SCHEME_CALLBACK (Stem_tremolo
,brew_molecule
,1);
124 Stem_tremolo::brew_molecule (SCM grob
)
126 Grob
*me
= unsmob_grob (grob
);
127 Grob
*stem
= unsmob_grob (me
->get_grob_property ("stem"));
128 Grob
*beam
= Stem::get_beam (stem
);
129 Direction stemdir
= Stem::get_direction (stem
);
130 Real beam_translation
= beam
? Beam::get_beam_translation (beam
) : 0.81;
132 Molecule mol
= raw_molecule (me
);
133 Interval mol_ext
= mol
.extent (Y_AXIS
);
134 Real ss
= Staff_symbol_referencer::staff_space (me
);
136 // ugh, rather calc from Stem_tremolo_req
137 int beam_count
= (beam
) ? (Stem::beam_multiplicity (stem
).length ()+ 1): 0;
144 Real beamthickness
= 0.0;
145 SCM sbt
= (beam
) ? beam
->get_grob_property ("thickness") : SCM_EOL
;
146 if (gh_number_p (sbt
))
148 beamthickness
= gh_scm2double (sbt
) * ss
;
152 = Stem::stem_end_position (stem
) *ss
/2
153 - stemdir
* (beam_count
* beamthickness
154 + ((beam_count
-1) >? 0) * beam_translation
);
157 the 0.33 ss is to compensate for the size of the note head
159 Real chord_start_y
= Stem::chord_start_y (stem
) +
162 Real padding
= beam_translation
;
165 if there is a flag, just above/below the notehead.
166 if there is not enough space, center on remaining space,
167 else one beamspace away from stem end.
169 if (!beam
&& Stem::duration_log (stem
) >= 3)
171 mol
.align_to (Y_AXIS
, -stemdir
);
172 mol
.translate_axis (chord_start_y
+ .5 * stemdir
, Y_AXIS
);
174 else if (stemdir
* (end_y
- chord_start_y
) - 2*padding
- mol_ext
.length () < 0.0)
176 mol
.translate_axis (0.5 * (end_y
+ chord_start_y
) - mol_ext
.center (),Y_AXIS
);
180 mol
.translate_axis (end_y
- stemdir
* beam_translation
185 return mol
.smobbed_copy ();
190 Stem_tremolo::set_stem (Grob
*me
,Grob
*s
)
192 me
->set_grob_property ("stem", s
->self_scm ());
196 ADD_INTERFACE (Stem_tremolo
,"stem-tremolo-interface",
198 "stem beam-width beam-thickness flag-count");