+2004-01-21 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * lily/stem.cc (thickness): new function.
+
+ * lily/staff-symbol.cc (get_ledger_line_thickness): new function:
+ compute thickness from ledger-line-thickness.
+
+ * lily/note-head.cc (brew_ledger_lines): use
+ Staff_symbol::get_ledger_line_thickness ().
+
+ * lily/beam.cc (rest_collision_callback): use
+ Staff_symbol_referencer::staff_space().
+
+ * lily/parser.yy (My_lily_lexer): change syntax: \newpartcombine
+ Mus1 Mus2
+
+ * lily/include/translator.hh (class Translator): add accepts_list_
+ so \with { \denies / \accepts } also works.
+
+ * scm/music-functions.scm (determine-split-list): determine split
+ list from music events.
+
+ * lily/new-part-combine-iterator.cc: more states.
+
+ * lily/moment.cc (LY_DEFINE): new function ly:moment<?
+
2004-01-20 Han-Wen Nienhuys <hanwen@xs4all.nl>
* lily/system.cc (set_loose_columns): use the right prebroken cols
@cindex Automatic beams
+@menu
+* Manual beams::
+* Setting automatic beam behavior::
+@end menu
+
+@node Manual beams
@subsection Manual beams
@cindex beams, manual
@cindex @code{]}
-@menu
-* Setting automatic beam behavior::
-@end menu
-
-@ignore
-@no de Beam typography
-@sub section Beam typography
-
-One of the strong points of LilyPond is how beams are formatted. Beams
-are quantized, meaning that the left and right endpoints beams start
-exactly on staff lines. Without quantization, small wedges of white
-space appear between the beam and staff line, and this looks untidy.
-
-Beams are also slope-damped: melodies that go up or down should also
-have beams that go up or down, but the slope of the beams should be
-less than the slope of the notes themselves.
-
-Some beams should be horizontal. These are so-called concave beams.
-
-[TODO: some pictures.]
-@end ignore
-
@node Setting automatic beam behavior
@subsection Setting automatic beam behavior
@cindex subscript
You can use the thumb-script to indicate that a note should be
-played with your thumb (used in cello music):
+played with the thumb. (used in cello music):
@lilypond[verbatim, singleline, fragment]
<a' a''-3>8(_\thumb <b' b''-3>)_\thumb
< c-1 e-2 g-3 b-5 > 4
@end lilypond
-Setting @code{fingeringOrientations} will put fingerings next
+@noindent
+In this case, setting @code{fingeringOrientations} will put fingerings next
to note heads:
@lilypond[verbatim,singleline,fragment,relative=1]
Internals: @internalsref{FingerEvent}, and @internalsref{Fingering}.
+Examples: @inputfileref{input/regression,finger-chords.ly}
@node Text scripts
@subsection Text scripts
@node The Lyrics context
@subsection The Lyrics context
-Lyrics are printed by interpreting them in @internalsref{LyricsVoice} context:
+Lyrics are printed by interpreting them in a @internalsref{LyricsVoice} context:
@example
\context LyricsVoice \lyrics @dots{}
@end example
\lyricsto @var{name} \new LyricsVoice @dots{}
@end example
-This aligns the lyrics to the notes of the @internalsref{Voice}
-context called @var{name}, which has to exist. Therefore, normally
-the @code{Voice} is specified first, and then the lyrics are specified
-with @code{\lyricsto}.
+This aligns the lyrics to the
+@c
+notes of the @internalsref{Voice} context called @var{name}, which has
+to exist. Therefore, normally the @code{Voice} is specified first, and
+then the lyrics are specified with @code{\lyricsto}.
For different or more complex orderings, the best way is to setup the
hierarchy of staves and lyrics first, e.g.
\lyricsto "soprano" \new LyricsVoice @emph{the lyrics}
@end example
-An example is in @inputfileref{input/template,satb.ly}.
+@noindent
+The final input would resemble
+
+@example
+ << \context ChoirStaff \notes << @emph{setup the music} >>
+ \lyricsto "soprano" @emph{etc}
+ \lyricsto "alto" @emph{etc}
+ @emph{etc}
+ >>
+@end example
+
+
+The @code{\lyricsto} command detects melismata: it only puts one
+syllable under a tied or slurred group of notes. If you want to force
+an unslurred group of notes to be a melisma, then insert
+@code{\melisma} after the first note of the group, and
+@code{\melismaEnd} after the last one, e.g.
+
+@lilypond[relative 1, singleline, fragment,verbatim]
+<< \context Voice = "lala" { \time 3/4
+ f4 g8
+ \melisma
+ f e f
+ \melismaEnd
+ e2 }
+ \lyricsto "lala" \new LyricsVoice \lyrics {
+ la di __ daah
+ } >>
+@end lilypond
+
+In addition, notes are considered a melisma if they are manually
+beamed, and automatic beaming (See @ref{Setting automatic beam
+behavior}) is switched off. The criteria for deciding melismata
+can be tuned with the property @code{melismaBusyProperties}. See
+@internalsref{Melisma_engraver} for more information.
When multiple stanzas are put on the same melody, it can happen that
two stanzas have melismata in different locations. This can be
the @code{ignoreMelismata} property to @code{#t}. An example is shown
in @inputfileref{input/regression,lyric-combine-new.ly}.
-
@cindex SATB
@cindex choral score
A complete example of a SATB score setup is in the file
@inputfileref{input/template,satb.ly}.
+@refcommands
+
+@code{\melisma}, @code{\melismaEnd}
+@cindex @code{\melismaEnd}
+@cindex @code{\melisma}
+
@seealso
-Internals: @internalsref{LyricCombineMusic}, @internalsref{Lyrics}
+Internals: @internalsref{LyricCombineMusic}, @internalsref{Lyrics},
+@internalsref{Melisma_engraver}.
Examples: @inputfileref{input/template,satb.ly},
@inputfileref{input/regression,lyric-combine-new.ly}.
Grob *common_x = rest->common_refpoint (beam, Y_AXIS);
Real rest_dim = rest->extent (common_x, Y_AXIS)[d] / staff_space * d;
- Real minimum_distance = robust_scm2double
+ Real minimum_distance =
+ staff_space * robust_scm2double
(rest->get_grob_property ("minimum-beam-collision-distance"), 1);
Real distance = beam_y - rest_dim;
shift = minimum_distance - distance;
else if (minimum_distance > distance)
shift = minimum_distance - distance;
-
- int stafflines = Staff_symbol_referencer::line_count (rest);
+
+ shift /= staff_space;
+
+ Real rad = Staff_symbol_referencer::line_count (rest) * staff_space / 2;
/* Always move discretely by half spaces */
- Real discrete_shift = ceil (shift * 2.0) / 2.0;
+ shift = ceil (shift * 2.0) / 2.0;
/* Inside staff, move by whole spaces*/
- if ((rest->extent (common_x, Y_AXIS)[d] + discrete_shift) * d
- < stafflines / 2.0
- ||(rest->extent (common_x, Y_AXIS)[-d] + discrete_shift) * -d
- < stafflines / 2.0)
- discrete_shift = ceil (discrete_shift);
+
+ if ((rest->extent (common_x, Y_AXIS)[d] + staff_space * shift) * d
+ < rad
+ || (rest->extent (common_x, Y_AXIS)[-d] + staff_space * shift) * -d
+ < rad)
+ shift = ceil (shift);
- return gh_double2scm (-d * discrete_shift);
+ return gh_double2scm (-d * staff_space * shift);
}
bool
Grob *me = unsmob_grob (smob);
Real staff_space = Staff_symbol_referencer::staff_space (me);
Real staff_size;
- Real thickness = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
- SCM lt = me->get_grob_property ("thickness");
- if (gh_number_p (lt))
- thickness *= gh_scm2double (lt);
+
+ Real thickness = Staff_symbol_referencer::line_thickness (me);
+ thickness *= robust_scm2double (me->get_grob_property ("thickness"), 1.0);
if (Staff_symbol_referencer::get_staff_symbol (me))
{
staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
Grob *me = unsmob_grob (smob);
Real staff_space = Staff_symbol_referencer::staff_space (me);
Real staff_size;
- Real thickness = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
- SCM lt = me->get_grob_property ("thickness");
- if (gh_number_p (lt))
- thickness *= gh_scm2double (lt);
+ Real thickness = Staff_symbol_referencer::line_thickness (me);
+ thickness *= robust_scm2double (me->get_grob_property ("thickness"), 1.0);
+
if (Staff_symbol_referencer::get_staff_symbol (me))
{
staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
Grob *me = unsmob_grob (smob);
Real staff_space = Staff_symbol_referencer::staff_space (me);
Real staff_size;
- Real thickness = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
- SCM lt = me->get_grob_property ("thickness");
- if (gh_number_p (lt))
- thickness *= gh_scm2double (lt);
+ Real thickness = Staff_symbol_referencer::line_thickness (me);
+ thickness *= robust_scm2double (me->get_grob_property ("thickness"), 1.0);
+
if (Staff_symbol_referencer::get_staff_symbol (me))
{
staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
Grob *me = unsmob_grob (smob);
Real staff_space = Staff_symbol_referencer::staff_space (me);
Real staff_size;
- Real thickness = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
- SCM lt = me->get_grob_property ("thickness");
- if (gh_number_p (lt))
- thickness *= gh_scm2double (lt);
+ Real thickness = Staff_symbol_referencer::line_thickness (me);
+ thickness *= robust_scm2double (me->get_grob_property ("thickness"), 1.0);
+
if (Staff_symbol_referencer::get_staff_symbol (me))
{
staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
i.grob_ = e;
if (!i.origin_trans_)
i.origin_trans_ = this;
+
+
+
get_daddy_grav ()->announce_grob (i);
}
Event_chord_iterator::get_req_translator ()
{
assert (report_to ());
- if (report_to ()->is_bottom_translator_b ())
+ if (report_to ()->is_bottom_context ())
return report_to ();
set_translator (report_to ()->get_default_interpreter ());
}
-/*
- TODO: use fontSize = NUMBER as a scaling constant: find the closest
- integer design size, and use magnification to do the fractional bit.
-*/
void
Font_size_engraver::acknowledge_grob (Grob_info gi)
{
SCM sz = get_property ("fontSize");
- if (gh_number_p (sz)
- && gh_scm2double (sz)
- && !gh_number_p (gi.grob_->get_grob_property ("font-size")))
+ /*
+ We only want to process a grob once.
+ */
+ if (gi.origin_trans_->daddy_trans_ != daddy_trans_)
+ return ;
+
+ if (gh_number_p (sz) && gh_scm2double (sz))
{
- gi.grob_->set_grob_property ("font-size", sz);
+ Real font_size = gh_scm2double (sz);
+
+ font_size += robust_scm2double (gi.grob_->get_grob_property ("font-size"), 0);
+ gi.grob_->set_grob_property ("font-size", gh_double2scm (font_size));
}
}
-
ENTER_DESCRIPTION(Font_size_engraver,
/* descr */ "Puts fontSize into font-relative-size grob property.",
/* creats*/ "",
(c) 1997--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
*/
+#include "staff-symbol-referencer.hh"
#include "molecule.hh"
#include "line-interface.hh"
#include "hairpin.hh"
}
bool continued = broken[Direction (-grow_dir)];
- Real height = robust_scm2double (me->get_grob_property ("height"), 0.2);
+ Real height = robust_scm2double (me->get_grob_property ("height"), 0.2) *
+ Staff_symbol_referencer::staff_space (me);
Real starth, endh;
if (grow_dir < 0)
ext.unite (gs[0]->extent (cx, X_AXIS));
Direction d = get_grob_direction (me);
- Real lt =me->get_paper()->get_realvar (ly_symbol2scm ("linethickness"));
- Real t = lt;
- SCM lthick = me->get_grob_property ("thickness");
- if (gh_number_p (lthick))
- t *= gh_scm2double (lthick);
+ Real thickness = Staff_symbol_referencer::line_thickness (me);
+ thickness *= robust_scm2double (me->get_grob_property ("thickness"), 1.0);
- Molecule b = Lookup::bracket (X_AXIS, ext, t, - d* 1.0, lt);
+ Molecule b = Lookup::bracket (X_AXIS, ext, thickness, - d* 1.0, thickness/2);
b.translate_axis ( - sp->get_bound (LEFT)->relative_coordinate (cx, X_AXIS), X_AXIS);
SCM ly_interval2scm (Drul_array<Real>);
Real robust_scm2double (SCM, double);
+int robust_scm2int (SCM, int);
Drul_array<Real> robust_scm2drul (SCM, Drul_array<Real>);
Interval robust_scm2interval (SCM, Drul_array<Real>);
Offset robust_scm2offset (SCM, Offset);
typeface. ie. leading is vertical space.
*/
+ static Real line_thickness (Grob*);
static Real staff_space (Grob*);
static Grob * get_staff_symbol (Grob*);
static bool on_staffline (Grob*);
{
public:
static Real staff_space (Grob*) ;
+ static Real get_line_thickness (Grob*);
+ static Real get_ledger_line_thickness (Grob*);
+
static int get_steps (Grob*) ;
static int line_count (Grob*);
DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM ));
static void set_stemend (Grob *,Real);
static Direction get_default_dir (Grob *);
static Slice Stem::beam_multiplicity (Grob *);
-
+ static Real thickness (Grob*);
static int head_count (Grob *);
static bool invisible_b (Grob *) ;
static Interval head_positions (Grob *);
void add_context_mod (SCM);
SCM default_child_context_name ();
SCM get_context_name () const;
- SCM get_accepted () const;
+ SCM get_accepted (SCM) const;
SCM get_property_ops () const { return property_ops_; }
SCM get_translator_names (SCM) const;
void set_acceptor (SCM accepts, bool add);
void add_used_group_translator (Translator *trans);
int get_depth () const;
- bool is_bottom_translator_b () const;
+ bool is_bottom_context () const;
bool is_removable () const;
void terminate_translator (Translator*r);
Translator *remove_translator (Translator*trans);
SCM definition_;
SCM properties_scm_;
SCM trans_group_list_;
-
+ SCM accepts_list_;
virtual SCM get_simple_trans_list ();
public:
DECLARE_SMOBS (Translator, dummy);
return o;
}
+
+
+int
+robust_scm2int (SCM k, int o)
+{
+ if (scm_integer_p (k) == SCM_BOOL_T)
+ o = gh_scm2int (k);
+
+ return o;
+}
Molecule
Line_interface::line (Grob *me, Offset from, Offset to)
{
- Real thick = me->get_paper()->get_realvar (ly_symbol2scm ("linethickness"));
- thick *= robust_scm2double (me->get_grob_property ("thickness"), 1.0); // todo: staff sym referencer?
-
+ Real thick = Staff_symbol_referencer::line_thickness (me);
SCM type = me->get_grob_property ("style");
SCM dash_fraction = me->get_grob_property ("dash-fraction");
Real dx = dz[X_AXIS];
Real dy = dz[Y_AXIS];
- Real thick = me->get_paper()->get_realvar (ly_symbol2scm ("linethickness"));
+ Real thick = Staff_symbol_referencer::thickness (me);
thick *= robust_scm2double (me->get_grob_property ("thickness"), 1.0); // todo: staff sym referencer?
Real staff_space = Staff_symbol_referencer::staff_space (me);
TODO: robustify.
*/
SCM which = me->get_grob_property ("style");
- SCM thick = me->get_grob_property ("thickness");
SCM height = me->get_grob_property ("height");
- Real t = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness")) * gh_scm2double (thick);
+ Real t = Staff_symbol_referencer::thickness (me) * robust_scm2double (me->get_grob_property ("thickness"));
Grob *common = me->get_bound(LEFT)->common_refpoint (me->get_bound (RIGHT),
X_AXIS);
/*
This can only be melisma-playing-event.
*/
- return melisma_busy (this);
+ return melisma_busy (this);
}
Melisma_engraver::Melisma_engraver()
Real staff_space = Staff_symbol_referencer::staff_space (me);
if (primitive & MLP_ANY)
{
- SCM thickness_scm = me->get_grob_property ("thickness");
- if (thickness_scm != SCM_EOL)
- {
- thickness = gh_scm2double (thickness_scm);
- }
- else
- {
- programming_error (_f ("Mensural_ligature:"
- "thickness undefined on flexa %d; assuming 1.4",
- primitive));
- thickness = 1.4 * me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
- }
+ thickness = robust_scm2double ( me->get_grob_property ("thickness"), .14);
}
if (primitive & MLP_FLEXA)
{
- SCM delta_pitch_scm = me->get_grob_property ("delta-pitch");
- if (delta_pitch_scm != SCM_EOL)
- {
- delta_pitch = gh_scm2int (delta_pitch_scm);
- }
- else
- {
- programming_error (_f ("Mensural_ligature:"
- "delta-pitch undefined on flexa %d; assuming 0",
- primitive));
- delta_pitch = 0;
- }
+ delta_pitch = robust_scm2int (me->get_grob_property ("delta-pitch"),
+ 0);
flexa_width = robust_scm2double (me->get_grob_property ("flexa-width"), 2.0 * staff_space);
}
return (*ma / *mb).smobbed_copy();
}
+LY_DEFINE (ly_moment_less_p,"ly:moment<?", 2,0,0, (SCM a, SCM b),
+ "Comparation.")
+{
+ Moment * ma = unsmob_moment (a);
+ Moment * mb = unsmob_moment (b);
+ SCM_ASSERT_TYPE (ma, a, SCM_ARG1, __FUNCTION__, "moment");
+ SCM_ASSERT_TYPE (mb, b, SCM_ARG2, __FUNCTION__, "moment");
+
+ return gh_bool2scm (*ma < *mb);
+}
+
SCM
Interpretation_context_handle one_;
Interpretation_context_handle two_;
+ Interpretation_context_handle null_;
Interpretation_context_handle shared_;
- void together ();
+ void chords_together ();
void apart ();
+ void solo1 ();
+ void solo2 ();
+ void unisono ();
};
}
void
-New_pc_iterator::together ()
+New_pc_iterator::chords_together ()
{
first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
+ first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ());
+ second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
+}
+
+
+void
+New_pc_iterator::solo1 ()
+{
+ first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
+ first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
+
+ second_iter_->substitute_outlet (two_.report_to (), null_.report_to ());
+ second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
}
+void
+New_pc_iterator::unisono ()
+{
+ /*
+ like solo1, but should set a2 string.
+ */
+ first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
+ first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
+
+ second_iter_->substitute_outlet (two_.report_to (), null_.report_to ());
+ second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
+}
+
+
+void
+New_pc_iterator::solo2 ()
+{
+ second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
+ second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ());
+
+ first_iter_->substitute_outlet (one_.report_to (), null_.report_to ());
+ first_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
+}
+
+
void
New_pc_iterator::apart ()
{
- first_iter_->substitute_outlet (shared_.report_to (),one_.report_to ());
+ first_iter_->substitute_outlet (null_.report_to (), one_.report_to ());
+ first_iter_->substitute_outlet (shared_.report_to (), one_.report_to ());
+
+ second_iter_->substitute_outlet (null_.report_to (), two_.report_to ());
second_iter_->substitute_outlet (shared_.report_to (), two_.report_to ());
}
split_list_ = get_music ()->get_mus_property ("split-list");
SCM lst = get_music ()->get_mus_property ("elements");
+ SCM props = scm_list_n (scm_list_n (ly_symbol2scm ("denies"), ly_symbol2scm ("Thread"), SCM_UNDEFINED),
+ scm_list_n (ly_symbol2scm ("consists"), ly_symbol2scm ("Rest_engraver"), SCM_UNDEFINED),
+ scm_list_n (ly_symbol2scm ("consists"), ly_symbol2scm ("Note_heads_engraver"), SCM_UNDEFINED),
+ SCM_UNDEFINED);
+
Translator_group *tr
= report_to ()->find_create_translator (ly_symbol2scm ("Voice"),
- "shared", SCM_EOL);
+ "shared",props);
+ Translator_group *null
+ = report_to ()->find_create_translator (ly_symbol2scm ("Devnull"),
+ "", SCM_EOL);
+ null_.set_translator (null);
tr->execute_pushpop_property (ly_symbol2scm ("NoteHead"),
ly_symbol2scm ("font-size"), gh_int2scm (3));
set_translator (tr);
Translator_group *one = tr->find_create_translator (ly_symbol2scm ("Voice"),
- "one", SCM_EOL);
+ "one", props);
one_.set_translator (one);
one->execute_pushpop_property (ly_symbol2scm ("Stem"),
Translator_group *two = tr->find_create_translator (ly_symbol2scm ("Voice"),
- "two", SCM_EOL);
+ "two", props);
two_.set_translator (two);
two_.report_to ()->execute_pushpop_property (ly_symbol2scm ("Stem"),
ly_symbol2scm ("direction"), gh_int2scm (-1));
if (*splitm > now)
break ;
- if (gh_cdar (split_list_) == ly_symbol2scm ("together"))
- together ();
- else if (gh_cdar (split_list_) == ly_symbol2scm ("apart"))
+ SCM tag = gh_cdar (split_list_);
+
+ if (tag == ly_symbol2scm ("chords"))
+ chords_together ();
+ else if (tag == ly_symbol2scm ("apart"))
apart ();
+ else if (tag == ly_symbol2scm ("unisono"))
+ unisono ();
+ else if (tag == ly_symbol2scm ("solo1"))
+ solo1 ();
+ else if (tag == ly_symbol2scm ("solo2"))
+ solo2 ();
else
- programming_error ("Unknown split directive.");
+ {
+ String s = "Unknown split directive: " + ly_symbol2string (tag);
+ programming_error (s);
+ }
}
if (first_iter_->ok ())
#include <math.h>
#include <ctype.h>
+#include "staff-symbol.hh"
#include "misc.hh"
#include "dots.hh"
#include "note-head.hh"
Real left_shorten,
bool take_space)
{
+ Grob *staff = Staff_symbol_referencer::get_staff_symbol (me);
Real inter_f = Staff_symbol_referencer::staff_space (me)/2;
int line_count = (abs (pos) < interspaces)
? 0
if (line_count)
{
Real ledgerlinethickness =
- (me->get_paper ()->get_realvar (ly_symbol2scm ("ledgerlinethickness")));
+ Staff_symbol::get_ledger_line_thickness (staff);
Real blotdiameter = ledgerlinethickness;
- // (me->get_paper ()->get_realvar (ly_symbol2scm ("blotdiameter")));
Interval y_extent =
Interval (-0.5*(ledgerlinethickness),
+0.5*(ledgerlinethickness));
if (st)
{
- Real thick = robust_scm2double (st->get_grob_property ("thickness"), 1)
- * st->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
+ Real thick = Stem::thickness (st);
note_head_width -= thick;
}
|
|
- */
+
+ Just a small amount, yes. In tight situations, it is even
+ possible to center the `8' directly below the note, dropping the
+ ottava line completely...
+
+ */
b = Molecule (Box (b.extent (X_AXIS),
Interval (0.1,0.1)),
$$ = p;
}
- | NEWPARTCOMBINE embedded_scm Music Music {
- Music * p= MY_MAKE_MUSIC("NewPartCombineMusic");
- p->set_mus_property ("elements", gh_list ($3->self_scm (),$4->self_scm (), SCM_UNDEFINED));
- p->set_mus_property ("split-list", $2);
- scm_gc_unprotect_object ($3->self_scm ());
- scm_gc_unprotect_object ($4->self_scm ());
+ | NEWPARTCOMBINE Music Music {
+ static SCM proc;
+ if (!proc)
+ proc = scm_c_eval_string ("make-new-part-combine-music");
- $$ = p;
+ SCM res = scm_call_1 (proc, gh_list ($2->self_scm (),
+ $3->self_scm (), SCM_UNDEFINED));
+ scm_gc_unprotect_object ($3->self_scm ());
+ scm_gc_unprotect_object ($2->self_scm ());
+ $$ = unsmob_music (res);
+ scm_gc_protect_object (res);
}
;
LY_DEFINE(ly_pitch_diff, "ly:pitch-diff", 2 ,0 ,0,
(SCM pitch, SCM root),
"Return pitch with value DELTA = PITCH - ROOT, ie, "
- "ROOT == (ly:pitch-transpose root delta).")
+ "ROOT == (ly:pitch-transpose PITCH DELTA).")
{
Pitch *p = unsmob_pitch (pitch);
Pitch *r = unsmob_pitch (root);
/*
Default position is on stem X, at stem end Y
*/
- Real stem_thickness =
- robust_scm2double (stem->get_grob_property ("thickness"), 1)
- * stem->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
+ Real stem_thickness = Stem::thickness (stem);
o += Offset (0.5 *
x_extent * (1 + Stem::get_direction (stem))
- ((dir + 1)/2) * stem_thickness
}
Real base_thick = robust_scm2double (me->get_grob_property ("thickness"), 1);
-
- Real thick = base_thick *
- me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
+ Real thick = base_thick * Staff_symbol_referencer::line_thickness (me);
Real ss = Staff_symbol_referencer::staff_space (me);
Bezier one = get_curve (me);
return 1.0;
}
+Real
+Staff_symbol_referencer::line_thickness (Grob*me)
+{
+ Grob * st = get_staff_symbol (me);
+ if (st)
+ return Staff_symbol::get_line_thickness (st);
+
+ return me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
+}
+
Real
Staff_symbol_referencer::get_position (Grob*me)
{
Real
Staff_symbol::staff_space (Grob*me)
{
- return robust_scm2double ( me->get_grob_property ("staff-space"), 1.0);
+ return robust_scm2double ( me->get_grob_property ("staff-space"), 1.0);
}
+Real
+Staff_symbol::get_line_thickness (Grob* me)
+{
+ Real lt = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
+
+ return robust_scm2double (me->get_grob_property ("thickness"), 1.0) * lt;
+}
+
+Real
+Staff_symbol::get_ledger_line_thickness (Grob * me)
+{
+ Real lt = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
+ SCM lt_pair = me->get_grob_property ("ledger-line-thickness");
+ Offset z = robust_scm2offset (lt_pair, Offset (1.0, 0.1));
+
+ return z[X_AXIS] * get_line_thickness(me) + z[Y_AXIS]* staff_space (me);
+}
ADD_INTERFACE (Staff_symbol,"staff-symbol-interface",
"or space) is position 0. The length of the symbol may be set by hand "
"through the @code{width} property. ",
- "width staff-space thickness line-count");
-
+ "ledger-line-thickness width staff-space thickness line-count");
heads.reverse ();
- Real thick = robust_scm2double (me->get_grob_property ("thickness"),1)
- * me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
+ Real thick = thickness (me);
Grob *hed = support_head (me);
Real w = Note_head::head_extent (hed,X_AXIS)[dir];
else
{
r = flag (me).extent (X_AXIS)
- +
- gh_scm2double (me->get_grob_property ("thickness"))
- * me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"))/2;
+ + thickness (me)/2;
}
return ly_interval2scm (r);
}
-
+Real
+Stem::thickness (Grob* me)
+{
+ return gh_scm2double (me->get_grob_property ("thickness"))
+ * Staff_symbol_referencer::line_thickness (me);
+}
MAKE_SCHEME_CALLBACK (Stem,brew_molecule,1);
Grob*me = unsmob_grob (smob);
Molecule mol;
Direction d = get_direction (me);
-
-
/*
- TODO: make the stem start a direction ?
+ TODO: make the stem start a direction ?
This is required to avoid stems passing in tablature chords...
*/
return SCM_EOL;
if (invisible_b (me))
- {
- return SCM_EOL;
- }
+ return SCM_EOL;
Real y1 = Staff_symbol_referencer::get_position (lh);
Real y2 = stem_end_position (me);
// URG
- Real stem_width = robust_scm2double (me->get_grob_property ("thickness"), 1)
- * me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
+ Real stem_width = thickness (me);
Real blot =
me->get_paper ()->get_realvar (ly_symbol2scm ("blotdiameter"));
if (attach)
{
Real rule_thick
- = robust_scm2double (me->get_grob_property ("thickness"), 1)
- * me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
+ = thickness (me);
r += - d * rule_thick * 0.5;
}
#include "engraver.hh"
/**
- This engraver swallows everything given to it silently. The purpose of
- this is to prevent spurious "event junked" warnings.
*/
class Swallow_engraver : public Engraver
{
{
return true;
}
+
+Swallow_engraver::Swallow_engraver ()
+{
+}
+
+ENTER_DESCRIPTION(Swallow_engraver,
+/* descr */ "This engraver swallows everything given to it silently. The purpose of "
+ "this is to prevent spurious \"event junked\" warnings.",
+/* creats*/ "",
+/* accepts */ "general-music",
+/* acks */ "",
+/* reads */ "",
+/* write */ "");
me->set_grob_property ("control-points", cp);
}
- Real thick =
- gh_scm2double (me->get_grob_property ("thickness"))
- * me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
+ Real thick
+ = Staff_symbol_referencer::thickness (me)
+ * robust_scm2double (me->get_grob_property ("thickness"), 1);
Bezier b;
int i = 0;
}
SCM
-Context_def::get_accepted () const
+Context_def::get_accepted (SCM user_mod) const
{
- SCM correct_order = scm_reverse (accept_mods_);
+ SCM mods = scm_reverse_x (scm_list_copy (accept_mods_),
+ user_mod);
SCM acc = SCM_EOL;
- for (SCM s = correct_order; gh_pair_p (s); s = gh_cdr (s))
+ for (SCM s = mods; gh_pair_p (s); s = gh_cdr (s))
{
SCM tag = gh_caar (s);
SCM sym = gh_cadar (s);
{
assert (gh_symbol_p (type_sym));
- SCM accepted = get_accepted ();
+ SCM accepted = get_accepted (SCM_EOL);
Link_array<Context_def> accepteds;
for (SCM s = accepted; gh_pair_p (s); s = ly_cdr (s))
SCM trans_names = get_translator_names (ops);
tg->simple_trans_list_ = names_to_translators (trans_names, tg);
-
+ tg->accepts_list_ = get_accepted (ops);
return tg;
}
return t->self_scm();
}
-
-/*
- Default child context as a SCM string, or something else if there is
- none.
-*/
-SCM
-Context_def::default_child_context_name ()
-{
- SCM d = get_accepted ();
- return gh_pair_p (d) ? ly_car (scm_last_pair (d)) : SCM_EOL;
-}
void
Context_def::apply_default_property_operations (Translator_group *tg)
{
get_translator_names (SCM_EOL)), l);
l = gh_cons (gh_cons (ly_symbol2scm ("description"), description_), l);
l = gh_cons (gh_cons (ly_symbol2scm ("aliases"), context_aliases_), l);
- l = gh_cons (gh_cons (ly_symbol2scm ("accepts"), get_accepted ()), l);
+ l = gh_cons (gh_cons (ly_symbol2scm ("accepts"), get_accepted (SCM_EOL)), l);
l = gh_cons (gh_cons (ly_symbol2scm ("property-ops"), property_ops_), l);
l = gh_cons (gh_cons (ly_symbol2scm ("context-name"), context_name_), l);
l = gh_cons (gh_cons (ly_symbol2scm ("group-type"), translator_group_type_), l);
if (existing)
return existing;
+
+ /*
+ TODO: use accepts_list_.
+ */
Link_array<Context_def> path
= unsmob_context_def (definition_)->path_to_acceptable_translator (n, get_output_def ());
return trans;
}
+
+/*
+ Default child context as a SCM string, or something else if there is
+ none.
+*/
+SCM
+default_child_context_name (Translator_group const *tg)
+{
+ return gh_pair_p (tg->accepts_list_)
+ ? ly_car (scm_last_pair (tg->accepts_list_))
+ : SCM_EOL;
+}
+
+
bool
-Translator_group::is_bottom_translator_b () const
+Translator_group::is_bottom_context () const
{
- return !gh_symbol_p (unsmob_context_def (definition_)->default_child_context_name ());
+ return !gh_symbol_p (default_child_context_name (this));
}
Translator_group*
Translator_group::get_default_interpreter ()
{
- if (!is_bottom_translator_b ())
+ if (!is_bottom_context ())
{
- SCM nm = unsmob_context_def (definition_)->default_child_context_name ();
+ SCM nm = default_child_context_name (this);
SCM st = get_output_def ()->find_translator (nm);
Context_def *t = unsmob_context_def (st);
Translator_group *tg = t->instantiate (output_def_, SCM_EOL);
add_fresh_group_translator (tg);
- if (!tg->is_bottom_translator_b ())
+ if (!tg->is_bottom_context ())
return tg->get_default_interpreter ();
else
return tg;
else
scm_display (ly_translator_name (s), port);
+ if (Translator_group *td=dynamic_cast<Translator_group*> (sc))
+ {
+ scm_puts ("=", port);
+ scm_puts (td->id_string_.to_str0 (), port);
+ }
+
scm_display (sc->simple_trans_list_, port);
/*
properties_scm_ = SCM_EOL;
definition_ = SCM_EOL;
daddy_trans_ =0;
+ accepts_list_ = SCM_EOL;
}
Translator::Translator ()
scm_gc_mark (me->trans_group_list_);
scm_gc_mark (me->definition_);
scm_gc_mark (me->properties_scm_);
+ scm_gc_mark (me->accepts_list_);
return me->properties_scm_;
}
if (bracket_visibility)
{
- SCM gap = me->get_grob_property ("gap");
+ Real ss = Staff_symbol_referencer::staff_space (me);
+ Real gap = robust_scm2double (me->get_grob_property ("gap"), 1.0)
+ * ss;
SCM fl = me->get_grob_property ("bracket-flare");
SCM eh = me->get_grob_property ("edge-height");
do {
flare[d] = height[d] = shorten[d] = 0.0;
if (is_number_pair (fl))
- flare[d] += gh_scm2double (index_get_cell (fl, d));
+ flare[d] += ss * gh_scm2double (index_get_cell (fl, d));
if (is_number_pair (eh))
- height[d] += gh_scm2double (index_get_cell (eh, d)) * - dir;
+ height[d] += - dir * ss *gh_scm2double (index_get_cell (eh, d));
if (is_number_pair (sp))
- shorten[d] += gh_scm2double (index_get_cell (sp, d));
+ shorten[d] += ss *gh_scm2double (index_get_cell (sp, d));
}
while (flip (&d) != LEFT);
Molecule brack = make_bracket (me, Y_AXIS,
Offset (w, ry - ly),
- height,
- gh_scm2double (gap),
- flare,
- shorten);
+ height, gap,
+ flare, shorten);
mol.add_molecule (brack);
}
Grob * commonx = common_refpoint_of_list (cols, me, X_AXIS);
Interval staff;
-
if (Grob * st = Staff_symbol_referencer::get_staff_symbol (me))
staff = st->extent (commony, Y_AXIS);
\paper { \paperTwenty }
+
+partCombineListener = \paper {
+ \translator {
+ \VoiceContext
+ \denies Thread
+ \consists Note_heads_engraver
+ \consists Rest_engraver
+ \type "Recording_group_engraver"
+ recordEventSequence = #notice-the-events-for-pc
+ }
+}
+
+#(set-part-combine-listener partCombineListener)
+
\include "dynamic-scripts-init.ly"
\include "spanners-init.ly"
instr = #'()
\accepts "Voice"
+ \accepts "Devnull"
}
\alias "Staff"
BarLine \override #'bar-size = #4
- VoltaBracket \override #'minimum-space = #15 % urg, in \pt
- VoltaBracket \override #'padding = #5 % urg, in \pt
+ VoltaBracket \override #'minimum-space = #15
+ VoltaBracket \override #'padding = #5
StaffSymbol \override #'line-count = #1
Stem \override #'neutral-direction = #1
\consistsend "Hara_kiri_engraver"
}
+\translator {
+ \name "Devnull"
+ \type "Engraver_group_engraver"
+ \consists "Swallow_engraver"
+ \description "Silently discards all musical information given to this context. "
+ }
+
\translator {
\VoiceContext
\name "TabVoice"
\consists "Tab_note_heads_engraver"
\remove "Fingering_engraver"
\remove "New_fingering_engraver"
-
+
+\description "Context for drawing notes in a Tab staff. "
Slur \override #'font-family = #'roman
Slur \override #'molecule-callback = #hammer-molecule-callback
Slur \override #'direction = #-1
draw_neo_mensural_open_head (staff_space#, noteheight#);
fet_endchar;
-fet_beginchar("Harmonic notehead (Neo-mensural open)","0harmonic","harmonichead")
+%
+% WL says the thin lines should be thinner.
+%
+
+fet_beginchar("Harmonic notehead (Neo-mensural open)",
+ "0harmonic","harmonichead")
+
draw_neo_mensural_open_head (1.3 staff_space#, 1.3 noteheight#);
charwx := head_width#;
charwy := 0;
(grob-property-description 'knee-spacing-correction number? "optical correction amount for knees. 0: no correction; 1: full correction.")
(grob-property-description 'layer number? "The output layer [0..2]. The default is 1.")
+(grob-property-description 'ledger-line-thickness number-pair?
+ "The thickness of ledger lines: it is the sum of 2 numbers.
+ The car is the factor for linethickness, and the cdr for staff space. Both contributions are added.")
(grob-property-description 'left-position number? "position of left part of spanner.")
(grob-property-description 'left-padding ly:dimension? "space left of accs.")
(self-alignment-Y . 0)
(script-priority . 100)
(font-family . number)
- (font-size . -4)
+ (font-size . -5) ; don't overlap when next to heads.
(font-shape . upright)
(meta . ((interfaces . (finger-interface font-interface text-script-interface text-interface side-position-interface self-alignment-interface item-interface ))))
))
. (
(molecule-callback . ,Staff_symbol::brew_molecule)
(line-count . 5)
+ (ledger-line-thickness (1.0 . 0.1))
(layer . 0)
(meta . ((interfaces . (staff-symbol-interface spanner-interface))))
))
grobs
))
-(define (symbol<? l r)
- (string<? (symbol->string l) (symbol->string r)))
+
(define (all-contexts-doc)
(let* (
(begin
(debug-enable 'debug)
(debug-enable 'backtrace)
- (read-enable 'positions)))
+ (read-enable 'positions) ))
(define-public (line-column-location line col file)
0
(if (< x 0) -1 1)))
+(define-public (symbol<? l r)
+ (string<? (symbol->string l) (symbol->string r)))
+
(define-public (!= l r)
(not (= l r)))
"define-grob-interfaces.scm"
"paper.scm"
+ "bla.scm"
))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
+;; part-combiner.
+
+
+
+(define noticed '())
+(define part-combine-listener '())
+(define-public (set-part-combine-listener x)
+ (set! part-combine-listener x))
+
+(define-public (notice-the-events-for-pc context lst)
+ (set! noticed (cons lst noticed)))
+
+(define-public (make-new-part-combine-music music-list)
+ (let*
+ ((m (make-music-by-name 'NewPartCombineMusic))
+ (m1 (context-spec-music (car music-list) 'Voice "one"))
+ (m2 (context-spec-music (cadr music-list) 'Voice "two"))
+ (props '((denies Thread)
+ (consists Rest_engraver)
+ (consists Note_heads_engraver)
+ ))
+ )
+
+
+ (ly:set-mus-property! m 'elements (list m1 m2))
+ (ly:set-mus-property! m1 'property-operations props)
+ (ly:set-mus-property! m2 'property-operations props)
+ (ly:run-translator m2 part-combine-listener)
+ (ly:run-translator m1 part-combine-listener)
+ (ly:set-mus-property! m 'split-list
+ (determine-split-list (reverse (car noticed)) (reverse (cadr noticed))))
+ (set! noticed '())
+
+ m))
+
+(define-public (determine-split-list evl1 evl2)
+ "EVL1 and EVL2 should be ascending"
+
+ (define ev1 (list->vector evl1))
+ (define ev2 (list->vector evl2))
+ (define (when v i)
+ (car (vector-ref v i)))
+ (define (what v i)
+ (cdr (vector-ref v i)))
+
+ (define chord-threshold 8)
+
+ (define result
+ (list->vector
+ (map (lambda (x)
+ (cons x 'together))
+ (uniq-list
+ (merge (map car evl1) (map car evl2) ly:moment<?)))))
+
+ (define (analyse-events i1 i2 ri
+ active1
+ active2)
+
+ (define (analyse-span-event active ev)
+ (let*
+ ((name (ly:get-mus-property ev 'name))
+ (key (cond
+ ((equal? name 'SlurEvent) 'slur)
+ ((equal? name 'TieEvent) 'tie)
+ ((equal? name 'Beam) 'beam)
+ (else #f)))
+ (sp (ly:get-mus-property ev 'span-direction)))
+
+ (if (and (symbol? key) (ly:dir? sp))
+ ((if (= sp STOP) delete! cons) key active))
+ ))
+
+ (define (get-note-evs v i)
+ (define (f? x)
+ (equal? (ly:get-mus-property x 'name) 'NoteEvent))
+ (filter f? (map car (what v i))))
+
+ (define (put x)
+ (set-cdr! (vector-ref result ri) x) )
+
+ (cond
+ ((= ri (vector-length result)) '())
+ ((= i1 (vector-length ev1)) (put 'apart))
+ ((= i2 (vector-length ev2)) (put 'apart))
+ (else
+ (let*
+ ((m1 (when ev1 i1))
+ (m2 (when ev2 i2)))
+
+ (if (not (or (equal? m1 (when result ri))
+ (equal? m2 (when result ri))))
+ (begin
+ (display
+ (list "<? M1,M2 != result :"
+ m1 m2 (when result ri)))
+ (scm-error "boem")))
+
+ (set! active1
+ (sort
+ (map (lambda (x) (analyse-span-event active1 (car x)))
+ (what ev1 i1)) symbol<?))
+ (set! active2
+ (sort (map (lambda (x) (analyse-span-event active2 (car x)))
+ (what ev2 i2)) symbol<?))
+
+ (cond
+ ((ly:moment<? m1 m2)
+ (put 'apart)
+ (analyse-events (1+ i1) i2 (1+ ri) active1 active2))
+ ((ly:moment<? m2 m1)
+ (put 'apart)
+ (analyse-events i1 (1+ i2) (1+ ri) active1 active2))
+ (else
+ (if (not (equal? active1 active2))
+ (put 'apart)
+
+ (let*
+ ((notes1 (get-note-evs ev1 i1))
+ (pitches1 (sort
+ (map (lambda (x) (ly:get-mus-property x 'pitch)) notes1) ly:pitch<?))
+ (notes2 (get-note-evs ev2 i2))
+ (pitches2 (sort
+ (map (lambda (x) (ly:get-mus-property x 'pitch)) notes2) ly:pitch<?))
+ )
+ (cond
+ ((equal? pitches1 pitches2) (put 'unisono))
+ ((> (length notes1) 1) (put 'apart))
+ ((> (length notes2) 1) (put 'apart))
+ (else
+ (let* ((diff (ly:pitch-diff (car pitches1) (car pitches1))))
+ (if (< (ly:pitch-steps diff) chord-threshold)
+ (put 'chords)
+ (put 'apart))
+ ))))
+ )
+ (analyse-events (1+ i1) (1+ i2) (1+ ri) active1 active2))
+ )))))
+
+
+ (analyse-events 0 0 0 '() '())
+ (display result)
+ (vector->list result))
-(define-public (determine-split-list ev1 ev2 state)
-#f )
+; (determine-split-list '((1 . 2) (3 . 4)) '((1 . 2) (3 . 4)))