+2004-08-01 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * lily/dynamic-text-spanner.cc (print): new file.
+
+ * scm/define-grobs.scm (all-grob-descriptions): add DynamicTextSpanner
+
+ * lily/engraver-group-engraver.cc (do_announces): reorder logic:
+ keep recursing into children in case a parent context inserts a
+ grob into a child context.
+
+ * lily/dynamic-engraver.cc (acknowledge_grob): add accidentals to
+
2004-07-31 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ * scm/define-markup-commands.scm (postscript): new markup command
+ \postscript
+
* Documentation/user/notation.itely (Formatting cue notes): new
section.
#include "accidental-placement.hh"
#include "arpeggio.hh"
#include "context.hh"
-#include "engraver-group-engraver.hh"
#include "engraver.hh"
#include "event.hh"
#include "item.hh"
class Dynamic_engraver : public Engraver
{
Item * script_;
- Spanner * finished_cresc_;
- Spanner * cresc_;
+ Spanner *line_spanner_;
+ Spanner *cresc_;
- Music* script_ev_;
+ Spanner *finished_line_spanner_;
+ Spanner *finished_cresc_;
+
+ Music *script_ev_;
+ Music *current_cresc_ev_;
- Music * current_cresc_ev_;
Drul_array<Music*> accepted_spanreqs_drul_;
- Spanner* line_spanner_;
- Spanner* finished_line_spanner_;
-
Link_array<Note_column> pending_columns_;
Link_array<Grob> pending_elements_;
{
script_ = make_item ("DynamicText", script_ev_->self_scm ());
script_->set_property ("text",
- script_ev_->get_property ("text"));
+ script_ev_->get_property ("text"));
if (Direction d = to_dir (script_ev_->get_property ("direction")))
set_grob_direction (line_spanner_, d);
Axis_group_interface::add_element (line_spanner_, script_);
-
}
Music *stop_ev = accepted_spanreqs_drul_ [STOP] ?
{
cresc_ = make_spanner ("Hairpin", accepted_spanreqs_drul_[START]->self_scm ());
cresc_->set_property ("grow-direction",
- scm_int2num ((start_type == "crescendo")
- ? BIGGER : SMALLER));
+ scm_int2num ((start_type == "crescendo")
+ ? BIGGER : SMALLER));
}
*/
else
{
- cresc_ = make_spanner ("TextSpanner", accepted_spanreqs_drul_[START]->self_scm ());
+ cresc_ = make_spanner ("DynamicTextSpanner", accepted_spanreqs_drul_[START]->self_scm ());
cresc_->set_property ("style", s);
context ()->set_property ((start_type
- + "Spanner").to_str0 (), SCM_EOL);
+ + "Spanner").to_str0 (), SCM_EOL);
s = get_property ((start_type + "Text").to_str0 ());
/*
FIXME: use get_markup () to check type.
if (ly_c_string_p (s) || ly_c_pair_p (s))
{
cresc_->set_property ("edge-text",
- scm_cons (s, scm_makfrom0str ("")));
+ scm_cons (s, scm_makfrom0str ("")));
context ()->set_property ((start_type + "Text").to_str0 (),
- SCM_EOL);
+ SCM_EOL);
}
}
cresc_->set_bound (LEFT, script_
- ? script_
- : unsmob_grob (get_property ("currentMusicalColumn")));
+ ? script_
+ : unsmob_grob (get_property ("currentMusicalColumn")));
Axis_group_interface::add_element (line_spanner_, cresc_);
add_bound_item (line_spanner_, cresc_->get_bound (LEFT));
-
}
}
}
void
Dynamic_engraver::typeset_all ()
{
- /*
- remove suicided spanners,
- ugh: we'll need this for every spanner, beam, slur
- Hmm, how to do this, cleanly?
- Maybe just check at typeset_grob ()?
- */
- if (finished_cresc_
- && !finished_cresc_->is_live ())
- finished_cresc_ = 0;
- if (finished_line_spanner_
- && !finished_line_spanner_->is_live ())
- finished_line_spanner_ = 0;
-
if (finished_cresc_)
{
if (!finished_cresc_->get_bound (RIGHT))
{
finished_cresc_->set_bound (RIGHT, script_
- ? script_
- : unsmob_grob (get_property ("currentMusicalColumn")));
+ ? script_
+ : unsmob_grob (get_property ("currentMusicalColumn")));
if (finished_line_spanner_)
add_bound_item (finished_line_spanner_,
finished_cresc_ =0;
}
- script_ = 0;
+ script_ = 0;
if (finished_line_spanner_)
{
/*
*/
- Grob * l = finished_line_spanner_->get_bound (LEFT );
+ Grob * l = finished_line_spanner_->get_bound (LEFT);
Grob * r = finished_line_spanner_->get_bound (RIGHT);
if (!r && l)
finished_line_spanner_->set_bound (RIGHT, l);
{
Side_position_interface::add_support (line_spanner_, i.grob_);
- }
+ }
}
}
+
ENTER_DESCRIPTION (Dynamic_engraver,
/* descr */
"This engraver creates hairpins, dynamic texts, and their vertical\n"
--- /dev/null
+
+/*
+ crescendo-text-spanner.cc -- implement Text_spanner
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2000--2004 Jan Nieuwenhuizen <janneke@gnu.org>
+
+ Revised over good by Han-Wen.
+*/
+
+#include "stencil.hh"
+#include "text-item.hh"
+#include "text-spanner.hh"
+#include "line-spanner.hh"
+#include "spanner.hh"
+#include "font-interface.hh"
+#include "dimensions.hh"
+#include "output-def.hh"
+#include "warn.hh"
+#include "paper-column.hh"
+
+
+
+class Dynamic_text_spanner
+{
+public:
+ DECLARE_SCHEME_CALLBACK (print, (SCM));
+ static bool has_interface (Grob*);
+};
+
+
+
+/*
+ This is a partial C&P from text-spanner.cc
+
+ Dynamic_text_spanner is similar, but
+
+ * does not require bracket functionality.
+
+ * should make room for spanning points (mf/f/mp texts).
+
+ * In the future, we should support
+
+ cresc - - - - poco - - - a - - - - poco - - -
+
+ as well
+
+
+ The cut & paste is rather inelegant, but text-spanner was a failed
+ and buggy attempt at being generic.
+
+
+*/
+MAKE_SCHEME_CALLBACK (Dynamic_text_spanner, print, 1);
+SCM
+Dynamic_text_spanner::print (SCM smob)
+{
+ Grob *me= unsmob_grob (smob);
+ Spanner *spanner = dynamic_cast<Spanner*> (me);
+
+ Grob *common = spanner->get_bound (LEFT)->common_refpoint (spanner->get_bound (RIGHT), X_AXIS);
+ Output_def * paper = me->get_paper ();
+
+ Interval span_points;
+ Drul_array<bool> broken;
+ Direction d = LEFT;
+ do
+ {
+ Item *b = spanner->get_bound (d);
+ broken[d] = b->break_status_dir () != CENTER;
+
+ if (broken[d])
+ {
+ if (d == LEFT)
+ span_points[d] = spanner->get_broken_left_end_align ();
+ else
+ span_points[d] = b->relative_coordinate (common, X_AXIS);
+ }
+ else
+ {
+ Real pad = 0.0;
+ Real encl = d;
+ if (b->internal_has_interface (ly_symbol2scm ("dynamic-interface")))
+ {
+ pad = robust_scm2double (me->get_property ("bound-padding"), 0.0);
+ encl = -d;
+ }
+
+ span_points[d] = -d * pad + b->extent (common, X_AXIS).linear_combination (encl);
+ }
+ }
+ while (flip (&d) != LEFT);
+
+
+ Stencil m;
+ SCM properties = Font_interface::text_font_alist_chain (me);
+ SCM edge_text = me->get_property ("edge-text");
+ Drul_array<Stencil> edge;
+ if (ly_c_pair_p (edge_text))
+ {
+ Direction d = LEFT;
+ do
+ {
+ if (broken[d])
+ continue;
+
+ SCM text = index_get_cell (edge_text, d);
+
+ if (Text_item::markup_p (text))
+ edge[d] = *unsmob_stencil (Text_item::interpret_markup (paper->self_scm (), properties, text));
+
+ if (!edge[d].is_empty ())
+ edge[d].align_to (Y_AXIS, CENTER);
+ }
+ while (flip (&d) != LEFT);
+ }
+
+ do
+ {
+ Interval ext = edge[d].extent (X_AXIS);
+ if (!ext.is_empty ())
+ {
+ edge[d].translate_axis (span_points[d], X_AXIS);
+ m.add_stencil (edge[d]);
+ span_points[d] += -d * ext[-d];
+ }
+ }
+ while (flip (&d) != LEFT);
+
+
+ if (!span_points.is_empty ())
+ {
+ Stencil l =Line_spanner::line_stencil (me,
+ Offset (span_points[LEFT], 0),
+ Offset (span_points[RIGHT], 0));
+ m.add_stencil (l);
+ }
+ m.translate_axis (- me->relative_coordinate (common, X_AXIS), X_AXIS);
+ return m.smobbed_copy ();
+}
+
+ADD_INTERFACE (Dynamic_text_spanner,
+ "crescendo-text-spanner-interface",
+ "A text spanner for crescendo texts",
+ "dash-period dash-fraction edge-text style thickness");
+
}
+/*
+ Ugh. This is slightly expensive. We could/should cache the value of
+ the group count?
+ */
+int
+Engraver_group_engraver::pending_grob_count () const
+{
+ int count = announce_infos_.size ();
+ for (SCM s = context ()->children_contexts ();
+ ly_c_pair_p (s); s = ly_cdr (s))
+ {
+ Context *c = unsmob_context (ly_car (s));
+ Engraver_group_engraver * group
+ =dynamic_cast<Engraver_group_engraver*> (c->implementation ());
+
+ if (group)
+ count += group->pending_grob_count ();
+ }
+ return count;
+}
+
void
Engraver_group_engraver::do_announces ()
{
- do
- {
- engraver_each (get_simple_trans_list (),
- &Engraver::process_acknowledged_grobs);
+ do {
+ for (SCM s = context ()->children_contexts ();
+ ly_c_pair_p (s); s = ly_cdr (s))
+ {
+ Context *c = unsmob_context (ly_car (s));
+ Engraver_group_engraver * group
+ = dynamic_cast<Engraver_group_engraver*> (c->implementation ());
+ if (group)
+ group->do_announces ();
+ }
+
+ do
+ {
+ engraver_each (get_simple_trans_list (),
+ &Engraver::process_acknowledged_grobs);
- if (!announce_infos_.size ())
- break;
+
+ if (announce_infos_.size () == 0)
+ break;
- acknowledge_grobs ();
- announce_infos_.clear ();
- }
- while (1);
+ acknowledge_grobs ();
+ announce_infos_.clear ();
+ }
+ while (1);
+
+ } while (pending_grob_count () > 0);
}
Direction grow_dir = to_dir (s);
-
- /* Ugh, must be same as Text_spanner::print. */
-
- /*
- Ugh. property name is not general.
- */
- Real padding = ly_scm2double (me->get_property ("if-text-padding"));
+ Real padding = ly_scm2double (me->get_property ("bound-padding"));
Drul_array<bool> broken;
Drul_array<Item*> bounds ;
ADD_INTERFACE (Hairpin, "hairpin-interface",
"A hairpin (de)crescendo.",
- "grow-direction height if-text-padding");
+ "grow-direction height bound-padding");
virtual void initialize ();
virtual void do_announces ();
virtual void announce_grob (Grob_info);
+
+ int pending_grob_count () const;
private:
virtual void acknowledge_grobs ();
};
virtual System *get_system () const;
virtual Paper_column *get_column () const;
virtual void handle_prebroken_dependencies ();
- static bool has_interface (Grob *);
+ static bool has_interface (Grob *);
protected:
virtual void discretionary_processing ();
void copy_breakable_items ();
public:
DECLARE_SCHEME_CALLBACK (print, (SCM));
static bool has_interface (Grob*);
-private:
- static void setup_pedal_bracket(Spanner *s);
};
#endif /* TEXT_SPANNER_HH */
#include "stencil.hh"
#include "text-item.hh"
-#include "text-spanner.hh"
#include "line-spanner.hh"
#include "spanner.hh"
#include "font-interface.hh"
{
height[LEFT] = 0;
- Real padding = robust_scm2double (me->get_property ("if-text-padding"), 0);
+ Real padding = robust_scm2double (me->get_property ("bound-padding"), 0);
span_points[LEFT] = padding
+ textbit->extent (common, X_AXIS)[RIGHT];
}
-
Stencil m ;
if (!span_points.is_empty () &&
ADD_INTERFACE (Piano_pedal_bracket,"piano-pedal-bracket-interface",
"The bracket of the piano pedal. It can be tuned through the regular "
"bracket properties.",
- "edge-height shorten-pair bracket-flare pedal-text");
+ "bound-padding edge-height shorten-pair bracket-flare pedal-text");
if (!to_boolean (get_property ("skipTypesetting")))
{
recurse_over_translators (context (), &Engraver::process_music, UP);
- recurse_over_translators (context (), &Engraver::do_announces, UP);
+ Engraver_group_engraver::do_announces();
}
recurse_over_translators (context (), &Translator::stop_translation_timestep, UP);
{
if (m->is_mus_type ("text-span-event"))
{
-
Direction d = to_dir (m->get_property ("span-direction"));
req_drul_[d] = m;
return true;
{
if (!span_)
{
- req_drul_[STOP]->origin ()->warning
- (_ ("can't find start of text spanner"));
+ req_drul_[STOP]->origin ()->warning (_ ("can't find start of text spanner"));
}
else
{
ADD_INTERFACE (Text_spanner,"text-spanner-interface",
"generic text spanner",
- "dash-period if-text-padding dash-fraction edge-height bracket-flare edge-text shorten-pair style thickness enclose-bounds");
+ "dash-period dash-fraction edge-height bracket-flare edge-text shorten-pair style thickness enclose-bounds");
if (dir == DOWN)
{
translator_each (tg->get_simple_trans_list (),
- ptr);
+ ptr);
(tg->*ptr) ();
}
called before line breaking, but after splitting breakable items at
potential line breaks.")
(between-cols ,pair? "Where to attach a loose column to")
+ (bound-padding ,number? "The amount of padding to insert around spanner bounds.")
(bracket-flare ,number-pair? "A pair of numbers specifying how
much edges of brackets should slant outward. Value 0.0 means straight
edges")
typeset on a Stem. Valid options include @code{()} and
@code{mensural}. Additionally, @code{\"no-flag\"} switches off the
flag.")
- (stroke-style ,string? "set to \"grace\" to turn stroke through flag on.")
(flag-width-function ,procedure? "Procedure that computes the width of a half-beam (a non-connecting beam.).")
(font-family ,symbol? "The font family is the broadest category for selecting text fonts. Options include: @code{sans}, @code{roman} ")
(font-encoding ,symbol? "The font encoding is the broadest
(font-shape ,symbol? "Select the shape of a font. Choices include @code{upright},
@code{italic}, @code{caps}.")
+ (forced-distance ,ly:dimension? "A fixed distance between object
+reference points in an alignment.")
+
(force-hshift ,number? "This specifies a manual shift for notes
in collisions. The unit is the note head width of the first voice
note. This is used by @internalsref{note-collision-interface}.")
directions, this amount is the correction for two normal sized stems
that overlap completely.")
(string-count ,integer? "The number of strings in a fret diagram.")
+ (stroke-style ,string? "set to \"grace\" to turn stroke through flag on.")
+
(style ,symbol? "This setting determines in what style a grob is
typeset. Valid choices depend on the @code{print-function} that is
reading this property.")
(thickness ,number? "Bar line thickness, measured in
@code{linethickness}.")
(thin-kern ,number? "The space after a hair-line in a bar line.")
- (forced-distance ,ly:dimension? "A fixed distance between object
-reference points in an alignment.")
(threshold ,number-pair? "(@var{min} . @var{max}), where
@var{min} and @var{max} are dimensions in staff space.")
(stem-info ,pair? "caching of stem parameters")
(note-columns ,pair? "list of NoteColumn grobs.")
- (if-text-padding ,number? "padding in case texts are there.")
(position-callbacks ,list? "list of
functions set spanner positions.")
(font-encoding . fetaDynamic)
(font-shape . italic)
(self-alignment-Y . 0)
- (meta . ((interfaces . (font-interface text-interface self-alignment-interface dynamic-interface script-interface item-interface))))
+ (meta . ((interfaces . (font-interface text-interface self-alignment-interface
+ dynamic-interface script-interface item-interface))))
))
+ (DynamicTextSpanner
+ . ((print-function . ,Dynamic_text_spanner::print)
+ (font-series . bold)
+ (font-shape . italic)
+ (style . dashed-line)
+ ; need to blend with dynamic texts.
+ (font-size . 2)
+ (bound-padding . 0.75)
+ (dash-fraction . 0.2)
+ (dash-period . 3.0)
+ (meta . ((interfaces . (font-interface
+ text-interface
+ dynamic-interface dynamic-text-spanner-interface
+ item-interface))))
+ ))
+
(DynamicLineSpanner
. (
(axes . (1))
(height . 0.6666)
(spacing-procedure . ,Spanner::set_spacing_rods)
(minimum-length . 2.0)
- (if-text-padding . 1.0)
+ (bound-padding . 1.0)
(self-alignment-Y . 0)
(Y-offset-callbacks . (,Self_alignment_interface::aligned_on_self))
(meta . ((interfaces . (hairpin-interface line-interface self-alignment-interface dynamic-interface spanner-interface))))
. (
(print-function . ,Piano_pedal_bracket::print)
(style . line)
- (if-text-padding . 1.0)
+ (bound-padding . 1.0)
(direction . -1)
(bracket-flare . (0.5 . 0.5))
(edge-height . (1.0 . 1.0))
(font-shape . italic)
(style . dashed-line)
(staff-padding . 0.1)
-
- ;; urg, only for (de)cresc. text spanners
- (if-text-padding . 1.0)
(dash-fraction . 0.2)
(dash-period . 3.0)
(direction . 1)
(make-simple-markup ""))
-(def-markup-command (postscript paper props str)
+(def-markup-command (postscript paper props str) (string?)
+
"This inserts @var{str} directly into the output as a PostScript command string."
- (string?)
(ly:make-stencil
(list 'embedded-ps str)
'(0 . 0) '(0 . 0) ))
def conv (str):
str = re.sub (r'neo_mensural', 'neomensural', str)
+ str = re.sub (r'if-text-padding', 'bound-padding', str)
return str
conversions.append (((2, 3, 9), conv,
- '''neo_mensural -> neomensural'''))
+ '''neo_mensural -> neomensural, if-text-padding -> bound-padding'''))
def conv_mode_experiment (str):