+2002-10-21 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+
+ * lily/text-item.cc (lookup_text): don't use virtual fonts for
+ normal texts.
+
+ * lily/multi-measure-rest-engraver.cc: make separate
+ MultiMeasureRestNumber grob. Introduce restNumberThreshold.
+
+ * lily/multi-measure-rest.cc: remove text handling. Remove number-threshold.
+
2002-10-20 Han-Wen Nienhuys <hanwen@cs.uu.nl>
* scm/music-types.scm: doc patch by Graham Percival
are not expanded when you set @code{Score.skipBars}. Although the
multi-measure-rest is a Spanner, minimum distances are set to keep it
colliding from barlines.
+
+Texts may be added to the rests by setting @code{text} in
+@code{MultiMeasureRestNumber.}
+
+Rests over measures during longer than 2 wholes use breve rests.
"
}
-\score { \notes { \time 3/4 \key cis \major
- R2.*15 R2. R2.*7 }
+\score { \notes {
+ \time 3/4 \key cis \major
+ R2.*15
+ R2.
+ \once \property Staff.MultiMeasureRestNumber \set #'text = #'(music "scripts-ufermata")
+ R2.
+ R2.*3
+ R2.*7
+\time 8/4 R1*2
+}
\paper {
\translator {
\ScoreContext
#include <math.h>
#include <libc-extension.hh> // isinf
+#include "self-alignment-interface.hh"
#include "side-position-interface.hh"
#include "axis-group-interface.hh"
#include "warn.hh"
ENTER_DESCRIPTION(Dot_column_engraver,
-/* descr */ " Engraves dots on dotted notes shifted to the right of the note.
-If omitted, then dots appear on top of the notes.
-",
+/* descr */ " Engraves dots on dotted notes shifted to the right of the note.\n"
+"If omitted, then dots appear on top of the notes.",
/* creats*/ "DotColumn",
/* accepts */ "",
/* acks */ "rhythmic-head-interface dot-column-interface stem-interface",
}
}
ENTER_DESCRIPTION(Dynamic_engraver,
-/* descr */ "
-This engraver creates hairpins, dynamic texts, and their vertical
-alignments. The symbols are collected onto a DynamicLineSpanner grob
-which takes care of vertical positioning.
-",
+/* descr */
+"This engraver creates hairpins, dynamic texts, and their vertical\n"
+"alignments. The symbols are collected onto a DynamicLineSpanner grob\n"
+"which takes care of vertical positioning. "
+,
/* creats*/ "DynamicLineSpanner DynamicText Hairpin TextSpanner",
/* accepts */ "absolute-dynamic-event crescendo-event decrescendo-event",
#include "event.hh"
#include "stem.hh"
#include "rhythmic-head.hh"
+#include "self-alignment-interface.hh"
class Fingering_engraver : public Engraver
{
class Multi_measure_rest
{
public:
-
static bool has_interface (Grob*);
DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM ));
DECLARE_SCHEME_CALLBACK (percent, (SCM));
static void add_column (Grob*,Item*);
DECLARE_SCHEME_CALLBACK (set_spacing_rods, (SCM ));
-
+ DECLARE_SCHEME_CALLBACK (centered_molecule, (SCM ));
+
static Molecule big_rest (Grob*,Real);
static Molecule symbol_molecule (Grob*,Real);
static Molecule church_rest (Grob*, Font_metric*, int,Real);
};
-struct Self_alignment_interface
-{
- static bool has_interface (Grob*);
- DECLARE_SCHEME_CALLBACK (aligned_on_self, (SCM element, SCM axis));
-DECLARE_SCHEME_CALLBACK (centered_on_parent, (SCM element, SCM axis));
-};
-
#endif /* SIDE_POSITION_INTERFACE_HH */
LY_DEFINE(ly_set_molecule_extent_x,"ly:set-molecule-extent!", 3 , 0, 0,
(SCM mol, SCM axis, SCM np),
- "Set the extent (@var{extent} must be a pair of numbers) of @var{mol} in
-@var{axis} direction (0 or 1 for x- and y-axis respectively).
-
-Note that an extent @code{(A . B)} is an interval and hence @code{A} is
-smaller than @code{B}, and is often negative.
-5")
+ "Set the extent (@var{extent} must be a pair of numbers) of @var{mol} in \n"
+"@var{axis} direction (0 or 1 for x- and y-axis respectively).\n"
+"\n"
+"Note that an extent @code{(A . B)} is an interval and hence @code{A} is\n"
+"smaller than @code{B}, and is often negative.\n"
+)
{
Molecule* m = unsmob_molecule (mol);
SCM_ASSERT_TYPE (m, mol, SCM_ARG1, __FUNCTION__, "molecule");
LY_DEFINE(ly_get_molecule_extent,
"ly:get-molecule-extent", 2 , 0, 0, (SCM mol, SCM axis),
- "Return a pair of numbers signifying the extent of @var{mol} in
-@var{axis} direction (0 or 1 for x and y axis respectively).
-")
+ "Return a pair of numbers signifying the extent of @var{mol} in "
+"@var{axis} direction (0 or 1 for x and y axis respectively)."
+)
{
Molecule *m = unsmob_molecule (mol);
SCM_ASSERT_TYPE (m, mol, SCM_ARG1, __FUNCTION__, "molecule");
"ly:combine-molecule-at-edge",
5 , 0, 0, (SCM first, SCM axis, SCM direction,
SCM second, SCM padding),
- "Construct a molecule by putting @var{second} next to
-@var{first}. @var{axis} can be 0 (x-axis) or 1 (y-axis), @var{direction} can be
--1 (left or down) or 1 (right or up). @var{padding} specifies extra
-space to add in between measured in global staff space.")
+ "Construct a molecule by putting @var{second} next to "
+"@var{first}. @var{axis} can be 0 (x-axis) or 1 (y-axis), @var{direction} can be "
+"-1 (left or down) or 1 (right or up). @var{padding} specifies extra "
+"space to add in between measured in global staff space.")
{
Molecule * m1 = unsmob_molecule (first);
LY_DEFINE(ly_make_molecule,
"ly:make-molecule", 3, 0, 0, (SCM expr, SCM xext, SCM yext),
- "
-The objective of any typesetting system is to put ink on paper in the
-right places. For LilyPond, this final stage is left to the @TeX{} and
-the printer subsystem. For lily, the last stage in processing a score is
-outputting a description of what to put where. This description roughly
-looks like
-@example
- PUT glyph AT (x,y)
- PUT glyph AT (x,y)
- PUT glyph AT (x,y)
-@end example
-you merely have to look at the tex output of lily to see this.
-Internally these instructions are encoded in Molecules.@footnote{At some
-point LilyPond also contained Atom-objects, but they have been replaced
-by Scheme expressions, making the name outdated.} A molecule is
-what-to-print-where information that also contains dimension information
-(how large is this glyph?).
-
-Conceptually, Molecules can be constructed from Scheme code, by
-translating a Molecule and by combining two molecules. In BNF
-notation:
-
-@example
-Molecule :: COMBINE Molecule Molecule
- | TRANSLATE Offset Molecule
- | GLYPH-DESCRIPTION
- ;
-@end example
-
-If you are interested in seeing how this information is stored, you
-can run with the @code{-f scm} option. The scheme expressions are then
-dumped in the output file.")
+ " \n"
+"The objective of any typesetting system is to put ink on paper in the \n"
+"right places. For LilyPond, this final stage is left to the @TeX{} and \n"
+"the printer subsystem. For lily, the last stage in processing a score is \n"
+"outputting a description of what to put where. This description roughly \n"
+"looks like \n"
+"@example \n"
+" PUT glyph AT (x,y) \n"
+" PUT glyph AT (x,y) \n"
+" PUT glyph AT (x,y) \n"
+"@end example \n"
+"you merely have to look at the tex output of lily to see this. \n"
+"Internally these instructions are encoded in Molecules.@footnote{At some \n"
+"point LilyPond also contained Atom-objects, but they have been replaced \n"
+"by Scheme expressions, making the name outdated.} A molecule is \n"
+"what-to-print-where information that also contains dimension information \n"
+"(how large is this glyph?). \n"
+" \n"
+"Conceptually, Molecules can be constructed from Scheme code, by \n"
+"translating a Molecule and by combining two molecules. In BNF \n"
+"notation: \n"
+" \n"
+"@example \n"
+"Molecule :: COMBINE Molecule Molecule \n"
+" | TRANSLATE Offset Molecule \n"
+" | GLYPH-DESCRIPTION \n"
+" ; \n"
+"@end example \n"
+" \n"
+"If you are interested in seeing how this information is stored, you \n"
+"can run with the @code{-f scm} option. The scheme expressions are then \n"
+"dumped in the output file.")
{
SCM_ASSERT_TYPE (ly_number_pair_p (xext), xext, SCM_ARG2, __FUNCTION__, "number pair");
SCM_ASSERT_TYPE (ly_number_pair_p (yext), yext, SCM_ARG3, __FUNCTION__, "number pair");
#include "multi-measure-rest.hh"
#include "paper-column.hh"
#include "engraver-group-engraver.hh"
-
+#include "side-position-interface.hh"
#include "staff-symbol-referencer.hh"
#include "engraver.hh"
#include "moment.hh"
int start_measure_;
Moment start_moment_;
- Spanner *mmrest_;
- Spanner *lastrest_;
-};
+ Spanner *mmrest_;
+ Spanner *number_;
+ Spanner *last_number_;
+ Spanner *last_rest_;
+};
Multi_measure_rest_engraver::Multi_measure_rest_engraver ()
{
start_measure_ = 0;
- mmrest_ = lastrest_ =0;
+ mmrest_ = 0;
+ last_rest_ =0;
+ number_ = 0;
new_req_ = busy_span_req_ = stop_req_ =0;
}
-
bool
Multi_measure_rest_engraver::try_music (Music* req)
{
if (busy_span_req_ && !mmrest_)
{
mmrest_ = new Spanner (get_property ("MultiMeasureRest"));
+ number_ = new Spanner (get_property ("MultiMeasureRestNumber"));
+
+ Side_position_interface::add_support (number_, mmrest_);
+ number_->set_parent (mmrest_, Y_AXIS);
- announce_grob(mmrest_, busy_span_req_->self_scm());
+ announce_grob (mmrest_, busy_span_req_->self_scm());
+ announce_grob (number_, busy_span_req_->self_scm());
start_measure_
= gh_scm2int (get_property ("currentBarNumber"));
}
Grob *cmc = unsmob_grob (get_property( "currentCommandColumn"));
Item *it = dynamic_cast<Item*> (cmc);
if (mmrest_)
- add_bound_item (mmrest_, it);
- if (lastrest_)
- add_bound_item (lastrest_,it);
+ {
+ add_bound_item (mmrest_, it);
+ add_bound_item (number_, it);
+ }
+ if (last_rest_)
+ {
+ add_bound_item (last_rest_,it);
+ add_bound_item (last_number_, it);
+ }
}
}
&& mmrest_->get_bound (LEFT) && mmrest_->get_bound (RIGHT))
{
typeset_grob (mmrest_);
+ typeset_grob (number_);
+ Side_position_interface::add_staff_support (number_);
/*
we must keep mmrest_ around to set measure-count, so
no mmrest_ = 0 here.
*/
+
+
}
- if (lastrest_)
+ if (last_rest_)
{
/* sanity check */
- if (lastrest_->get_bound (LEFT) && lastrest_->get_bound (RIGHT)
- && lastrest_->get_bound (LEFT) != lastrest_->get_bound (RIGHT))
- typeset_grob (lastrest_);
- lastrest_ = 0;
+ if (last_rest_->get_bound (LEFT) && last_rest_->get_bound (RIGHT)
+ && last_rest_->get_bound (LEFT) != last_rest_->get_bound (RIGHT))
+ {
+ typeset_grob (last_rest_);
+ typeset_grob (last_number_);
+ }
+ last_rest_ = 0;
+ last_number_ = 0;
}
if (new_req_)
if (mmrest_ && !mp.to_bool ())
{
- lastrest_ = mmrest_;
+ last_rest_ = mmrest_;
+ last_number_ = number_;
+
int cur = gh_scm2int (get_property ("currentBarNumber"));
- lastrest_->set_grob_property ("measure-count",
- gh_int2scm (cur - start_measure_));
+ int num = cur - start_measure_;
+ last_rest_->set_grob_property ("measure-count", gh_int2scm (num));
+
SCM sml = get_property ("measureLength");
Rational ml = (unsmob_moment (sml)) ? unsmob_moment (sml)->main_part_ : Rational (1);
- if (ml < Rational (2))
- {
- lastrest_->set_grob_property ("use-breve-rest", SCM_BOOL_F);
- }
- else
+ if (ml >= Rational (2))
{
- lastrest_->set_grob_property ("use-breve-rest", SCM_BOOL_T);
+ last_rest_->set_grob_property ("use-breve-rest", SCM_BOOL_T);
}
mmrest_ = 0;
+
+ SCM text =last_number_->get_grob_property ("text");
+ SCM thres = get_property ("restNumberThreshold");
+ int t = 1;
+ if (gh_number_p (thres))
+ t = gh_scm2int (thres);
+
+ if (text == SCM_EOL && num <= t)
+ last_number_->suicide();
+ else if (text == SCM_EOL)
+ {
+ text = scm_number_to_string (gh_int2scm (num), SCM_MAKINUM (10));
+ last_number_->set_grob_property ("text", text);
+ }
}
}
Multi_measure_rest_engraver::finalize ()
{
if (mmrest_)
- typeset_grob (mmrest_);
- if (lastrest_)
- typeset_grob (lastrest_);
+ {
+ typeset_grob (mmrest_);
+ typeset_grob (number_);
+ }
+ if (last_rest_)
+ {
+ typeset_grob (last_rest_);
+ typeset_grob (last_number_);
+ }
}
ENTER_DESCRIPTION(Multi_measure_rest_engraver,
-/* descr */ "Engraves multi-measure rests that are produced with @code{R}. Reads
-measurePosition and currentBarNumber to determine what number to print over the MultiMeasureRest.
-Reads measureLength to determine if it should use a whole rest or a breve rest to represent 1 measure
-
-",
-/* creats*/ "MultiMeasureRest",
+/* descr */
+ "Engraves multi-measure rests that are produced with @code{R}. Reads "
+"measurePosition and currentBarNumber to determine what number to print "
+"over the MultiMeasureRest. Reads measureLength to determine if it "
+"should use a whole rest or a breve rest to represent 1 measure "
+ ,
+/* creats*/ "MultiMeasureRest MultiMeasureRestNumber",
/* accepts */ "multi-measure-rest-event",
/* acks */ "",
-/* reads */ "currentBarNumber currentCommandColumn measurePosition measureLength",
+/* reads */ "currentBarNumber restNumberThreshold currentCommandColumn measurePosition measureLength",
/* write */ "");
#include "percent-repeat-item.hh"
#include "lookup.hh"
-
MAKE_SCHEME_CALLBACK (Multi_measure_rest,percent,1);
SCM
Multi_measure_rest::percent (SCM smob)
return r.smobbed_copy ();
}
-
-/*
- [TODO] 17
- variable-sized multi-measure rest symbol: |====| ??
-*/
MAKE_SCHEME_CALLBACK (Multi_measure_rest,brew_molecule,1);
SCM
Multi_measure_rest::brew_molecule (SCM smob)
Grob *me = unsmob_grob (smob);
Spanner * sp = dynamic_cast<Spanner*> (me);
- SCM alist_chain = Font_interface::font_alist_chain (me);
-
Interval sp_iv;
Direction d = LEFT;
measures = gh_scm2int (m);
}
- SCM s = me->get_grob_property ("number-threshold");
- if (measures > gh_scm2int (s))
- {
- Molecule s = Text_item::text2molecule (me,
- scm_makfrom0str (to_string (measures).to_str0 ()),
- alist_chain);
-
- s.align_to (X_AXIS, CENTER);
- s.translate_axis (gh_scm2double (me->get_grob_property ("padding")) + 2,
- Y_AXIS);
-
- s.translate_axis (mol.extent (X_AXIS).center (), X_AXIS);
- mol.add_molecule (s);
- }
mol.translate_axis (x_off, X_AXIS);
return mol.smobbed_copy ();
}
+
Molecule
Multi_measure_rest::symbol_molecule (Grob *me, Real space)
{
SCM alist_chain = Font_interface::font_alist_chain (me);
- SCM style_chain =
- Font_interface::add_style (me, ly_symbol2scm ("mmrest-symbol"),
- alist_chain);
-
Real staff_space = Staff_symbol_referencer::staff_space (me);
Font_metric *musfont
- = Font_interface::get_font (me,style_chain);
+ = Font_interface::get_font (me,alist_chain);
SCM sml = me->get_grob_property ("use-breve-rest");
-
if (measures == 1)
{
if (sml == SCM_BOOL_T)
-ADD_INTERFACE (Multi_measure_rest,"multi-measure-rest-interface",
- "A rest that spans a whole number of measures. For typesetting the
-numbers, fields from font-interface may be used.
+ADD_INTERFACE (Multi_measure_rest,"multi-measure-rest-interface",
+ "A rest that spans a whole number of measures.\n",
+ "expand-limit measure-count thickness use-breve-rest");
-",
- "expand-limit measure-count number-threshold padding thickness use-breve-rest");
-#include "side-position-interface.hh"
+#include "self-alignment-interface.hh"
#include "warn.hh"
/*
+/*
+ Position centered on parent.
+ */
+MAKE_SCHEME_CALLBACK (Self_alignment_interface,centered_on_other_axis_parent,2);
+SCM
+Self_alignment_interface::centered_on_other_axis_parent (SCM element_smob,
+ SCM axis)
+{
+ Grob *me = unsmob_grob (element_smob);
+ Axis a = (Axis) gh_scm2int (axis);
+ Grob *him = me->get_parent (other_axis (a));
+ Interval he = him->extent (him,a);
+
+ return gh_double2scm (he.empty_b () ? 0.0 : he.center ());
+}
+
+
+
/**
callback that centers the element on itself
#include "all-font-metrics.hh"
#include "afm.hh"
#include "lookup.hh"
-
+#include "virtual-font-metric.hh"
/*
}
+
Molecule
Text_item::lookup_text (Grob *, Font_metric*fm, SCM text)
{
SCM list = scm_list_n (ly_symbol2scm ("text"), text, SCM_UNDEFINED);
- list = fontify_atom (fm, list);
+
+ if (dynamic_cast<Virtual_font_metric*> (fm))
+ {
+ /*
+ ARGH.
+ */
+ programming_error ("Can't use virtual font for text.");
+ }
+ else
+ list = fontify_atom (fm, list);
return Molecule (fm->text_dimension (ly_scm2string (text)), list);
}
(Y-offset-callbacks . (,Staff_symbol_referencer::callback))
(staff-position . 0)
(expand-limit . 10)
- (number-threshold . 1)
- (padding . 1)
(thickness . 6.6)
- (use-breve-rest . #f)
- (font-family . number)
(padding . 1)
(meta . ((interfaces . (multi-measure-rest-interface rest-interface font-interface staff-symbol-referencer-interface spanner-interface))))
))
+
+ (MultiMeasureRestNumber
+ . (
+ (molecule-callback . ,Text_item::brew_molecule)
+ (X-offset-callbacks . (,Self_alignment_interface::aligned_on_self
+ ,Self_alignment_interface::centered_on_other_axis_parent))
+ (Y-offset-callbacks . (,Side_position_interface::aligned_side))
+ (self-alignment-X . 0)
+ (direction . 1)
+ (padding . 2)
+ (font-family . number)
+ (meta . ((interfaces . (side-position-interface font-interface spanner-interface))))
+ ))
+
(NoteCollision
. (
(grob-property-description 'non-default boolean? "not set because of existence of a bar?.")
(grob-property-description 'note-head-style string? "name of the font character to be used as note heads in the ambitus grob.")
(grob-property-description 'note-heads grob-list? "List of note head grobs")
-(grob-property-description 'number-threshold number? "only put numbers bigger than this threshold over multi measure rest.")
(grob-property-description 'old-accidentals list? "list of (pitch, accidental) pairs.")
(grob-property-description 'outer boolean? "whether a text spanner should extend to the outer edge of the spanned notes")
(grob-property-description 'padding number? "add this much extra space between objects that are next to each other.")
Description of scripts. This is used by Script_engraver for typesetting note-super/subscripts. See @file{scm/script.scm} for more information
")
+(translator-property-description 'restNumberThreshold number?
+ "If a multimeasure rest takes less
+than this number of measures, no number is printed. ")
+
(translator-property-description 'scriptHorizontal boolean? " Put
scripts left or right of note heads. Support for this is limited.
Accidentals will collide with scripts.