+1.3.95.jcn1
+===========
+
+* Added a generic Text spanner.
+
1.3.94.uu1
==========
MAJOR_VERSION=1
MINOR_VERSION=3
PATCH_LEVEL=95
-MY_PATCH_LEVEL=
+MY_PATCH_LEVEL=jcn1
# use the above to send patches: MY_PATCH_LEVEL is always empty for a
# released version.
--- /dev/null
+\score{
+ \notes\relative c''{
+ \property Voice.TextSpanner \push #'edge-text = #'("8 " . "")
+ a \spanrequest \start "text"
+ b c
+ a \spanrequest \stop "text"
+ \property Voice.TextSpanner \pop #'type
+ \property Voice.TextSpanner \push #'type = #"dotted-line"
+ a \spanrequest \start "text"
+ b c
+ a \spanrequest \stop "text"
+ \property Voice.TextSpanner \pop #'type
+ \property Voice.TextSpanner \push #'type = #"dashed-line"
+ a \spanrequest \start "text"
+ b c
+ a \spanrequest \stop "text"
+ \property Voice.TextSpanner \push #'dash-length = #5
+ \property Voice.TextSpanner \push #'line-thickness = #10
+ a \spanrequest \start "text"
+ b c
+ a \spanrequest \stop "text"
+ }
+}
if (line_spanner_)
line_spanner_->suicide ();
line_spanner_ = 0;
+ if (cresc_p_)
+ cresc_p_->suicide ();
+ cresc_p_ = 0;
}
else if ((s->span_type_str_ == "crescendo"
|| s->span_type_str_ == "decrescendo"))
--- /dev/null
+/*
+ text-spanner.hh -- declare Text_spanner
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2000 Jan Nieuwenhuizen <janneke@gnu.org>
+*/
+
+
+#ifndef TEXT_SPANNER_HH
+#define TEXT_SPANNER_HH
+
+#include "lily-guile.hh"
+
+class Text_spanner
+{
+public:
+ DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM));
+ static bool has_interface (Score_element*);
+};
+
+#endif /* TEXT_SPANNER_HH */
Score_element *me = unsmob_element (smob);
Interval iv;
- Score_element *common = me;
+ //Score_element *common = me;
+ Score_element *common = 0;
for (SCM s = me->get_elt_property ("arpeggios"); gh_pair_p (s); s = gh_cdr (s))
{
Score_element *arpeggio = unsmob_element (gh_car (s));
- common = arpeggio->common_refpoint (common, Y_AXIS);
+ if (common)
+ common = arpeggio->common_refpoint (common, Y_AXIS);
+ else
+ common = arpeggio;
}
- // Hmm, nothing in common?
- if (0) //common)
+ if (0) //common)
for (SCM s = me->get_elt_property ("arpeggios"); gh_pair_p (s); s = gh_cdr (s))
{
Score_element *arpeggio = unsmob_element (gh_car (s));
+ // this dumps core: someone has no y-parent
Real c = common->relative_coordinate (arpeggio, Y_AXIS);
//iv.unite (Arpeggio::head_positions (stem));
iv.unite (Interval (c, c));
--- /dev/null
+/*
+ text-spanner-engraver.cc -- implement Text_spanner_engraver
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2000 Jan Nieuwenhuizen <janneke@gnu.org>
+*/
+
+#include "dimensions.hh"
+#include "musical-request.hh"
+#include "paper-column.hh"
+#include "note-column.hh"
+#include "item.hh"
+#include "side-position-interface.hh"
+#include "engraver.hh"
+#include "group-interface.hh"
+#include "directional-element-interface.hh"
+#include "translator-group.hh"
+#include "axis-group-interface.hh"
+
+
+class Text_spanner_engraver : public Engraver
+{
+public:
+ VIRTUAL_COPY_CONS (Translator);
+ Text_spanner_engraver ();
+
+protected:
+ virtual void do_removal_processing ();
+ virtual void acknowledge_element (Score_element_info);
+ virtual bool do_try_music (Music *);
+ virtual void do_process_music ();
+ virtual void do_pre_move_processing ();
+ virtual void do_post_move_processing ();
+
+private:
+ Spanner *span_;
+ Spanner *finished_;
+ Span_req *current_req_;
+ Drul_array<Span_req*> req_drul_;
+ void typeset_all ();
+};
+
+ADD_THIS_TRANSLATOR (Text_spanner_engraver);
+
+
+Text_spanner_engraver::Text_spanner_engraver ()
+{
+ finished_ = 0;
+ current_req_ = 0;
+ span_ =0;
+ req_drul_[START] = 0;
+ req_drul_[STOP] = 0;
+}
+
+void
+Text_spanner_engraver::do_post_move_processing ()
+{
+ req_drul_[START] = 0;
+ req_drul_[STOP] = 0;
+}
+
+bool
+Text_spanner_engraver::do_try_music (Music *m)
+{
+ if (Span_req *s = dynamic_cast <Span_req*> (m))
+ {
+ if (s->span_type_str_ == "abort")
+ {
+ req_drul_[LEFT] = 0;
+ req_drul_[RIGHT] = 0;
+ if (span_)
+ span_->suicide ();
+ span_ = 0;
+ }
+ else if (s->span_type_str_ == "text")
+ {
+ req_drul_[s->span_dir_] = s;
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+Text_spanner_engraver::do_process_music ()
+{
+ if (req_drul_[STOP])
+ {
+ if (!span_)
+ {
+ req_drul_[STOP]->origin ()->warning
+ (_ ("can't find start of text spanner"));
+ }
+ else
+ {
+ assert (!finished_);
+ Score_element* e = unsmob_element (get_property ("currentMusicalColumn"));
+ span_->set_bound (RIGHT, e);
+
+ finished_ = span_;
+ span_ = 0;
+ current_req_ = 0;
+ }
+ }
+
+ if (req_drul_[START])
+ {
+ if (current_req_)
+ {
+ req_drul_[START]->origin ()->warning
+ (_ ("already have a text spanner"));
+ }
+ else
+ {
+ current_req_ = req_drul_[START];
+ span_ = new Spanner (get_property ("TextSpanner"));
+ Side_position::set_axis (span_, Y_AXIS);
+ Score_element *e = unsmob_element (get_property ("currentMusicalColumn"));
+ span_->set_bound (LEFT, e);
+ announce_element (span_, req_drul_[START]);
+ }
+ }
+}
+
+void
+Text_spanner_engraver::acknowledge_element (Score_element_info info)
+{
+ if (span_ && Note_column::has_interface (info.elem_l_))
+ {
+ Side_position::add_support (span_, info.elem_l_);
+ add_bound_item (span_, dynamic_cast<Item*> (info.elem_l_));
+ }
+}
+
+void
+Text_spanner_engraver::typeset_all ()
+{
+ if (finished_)
+ {
+ typeset_element (finished_);
+ finished_ = 0;
+ }
+}
+
+void
+Text_spanner_engraver::do_pre_move_processing ()
+{
+ typeset_all ();
+}
+
+void
+Text_spanner_engraver::do_removal_processing ()
+{
+ typeset_all ();
+ if (span_)
+ {
+ current_req_->origin ()->warning (_ ("unterminated text spanner"));
+ span_->suicide ();
+ span_ = 0;
+ }
+}
+
--- /dev/null
+/*
+ text-spanner.cc -- implement Text_spanner
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2000 Jan Nieuwenhuizen <janneke@gnu.org>
+*/
+
+#include "molecule.hh"
+#include "text-spanner.hh"
+#include "spanner.hh"
+#include "lookup.hh"
+#include "dimensions.hh"
+#include "paper-def.hh"
+#include "debug.hh"
+#include "paper-column.hh"
+#include "staff-symbol-referencer.hh"
+
+/*
+ Generic Text spanner:
+
+ type: "line", "dashed-line", "dotted-line"
+ text: "text"
+ edge-text: ("le" . "re")
+ text-style: "italic"
+
+ not-yet-text
+ le -------------- re
+
+ TODO:
+ - vertical start / vertical end (fixme-name) |
+ - contination types (vert. star, vert. end) |-> eat volta-spanner
+ - more styles
+ - more texts/positions
+ - style: hairpin ?
+ */
+
+MAKE_SCHEME_CALLBACK (Text_spanner, brew_molecule, 1);
+
+SCM
+Text_spanner::brew_molecule (SCM smob)
+{
+ Score_element *me= unsmob_element (smob);
+ Spanner *spanner = dynamic_cast<Spanner*> (me);
+
+ Real staff_space = Staff_symbol_referencer::staff_space (me);
+ Real line = me->paper_l ()->get_var ("stafflinethickness");
+
+
+ Drul_array<bool> broken;
+ Direction d = LEFT;
+ do
+ {
+ Paper_column* s = dynamic_cast<Paper_column*>(spanner->get_bound (d)); // UGH
+ broken[d] = (!s->musical_b ());
+ }
+ while (flip (&d) != LEFT);
+
+ SCM s = me->get_elt_property ("text-style");
+ String text_style = "italic";
+ if (gh_string_p (s))
+ text_style = ly_scm2string (s);
+
+ SCM edge_text = me->get_elt_property ("edge-text");
+ Drul_array<Molecule> edge;
+ if (gh_pair_p (edge_text))
+ {
+ edge[LEFT] = me->lookup_l ()->text (text_style,
+ ly_scm2string (gh_car (edge_text)),
+ me->paper_l ());
+ if (!edge[LEFT].empty_b ())
+ edge[LEFT].align_to (Y_AXIS, CENTER);
+ edge[RIGHT] = me->lookup_l ()->text (text_style,
+ ly_scm2string (gh_cdr (edge_text)),
+ me->paper_l ());
+ if (!edge[RIGHT].empty_b ())
+ edge[RIGHT].align_to (Y_AXIS, CENTER);
+ }
+
+ Drul_array<Real> shorten;
+ shorten[LEFT] = 0;
+ shorten[RIGHT] = 0;
+
+ s = me->get_elt_property ("shorten");
+ if (gh_pair_p (s))
+ {
+ shorten[LEFT] = gh_scm2double (gh_car (s)) * staff_space;
+ shorten[RIGHT] = gh_scm2double (gh_cdr (s)) * staff_space;
+ }
+
+ Real broken_left = spanner->get_broken_left_end_align ();
+ Real width = spanner->spanner_length ();
+ width += spanner->get_bound (RIGHT)->extent (X_AXIS).length ();
+ width -= broken_left;
+ width -= shorten[LEFT] + shorten[RIGHT];
+ width -= edge[LEFT].extent (X_AXIS).length ()
+ + edge[RIGHT].extent (X_AXIS).length ();
+
+ if (width < 0)
+ {
+ warning (_ ("Text_spanner too small"));
+ width = 0;
+ }
+
+
+ String type = "dashed-line";
+ s = me->get_elt_property ("type");
+ if (gh_string_p (s))
+ type = ly_scm2string (s);
+
+ Real height;
+ SCM at;
+ if (type == "line"
+ || type == "dashed-line"
+ || type == "dotted-line")
+ {
+ Real thick = line;
+ s = me->get_elt_property ("line-thickness");
+ if (gh_number_p (s))
+ thick *= gh_scm2double (s);
+
+ // maybe these should be in line-thickness?
+ Real length = staff_space;
+ s = me->get_elt_property ("dash-length");
+ if (gh_number_p (s))
+ length = gh_scm2double (s) * staff_space;
+
+ Real period = 2 * length + thick;
+ s = me->get_elt_property ("dash-period");
+ if (gh_number_p (s))
+ period = gh_scm2double (s) * staff_space;
+
+ if (type == "dotted-line")
+ length = thick;
+
+ if (type == "line")
+ length = period + thick;
+
+ Real on = length - thick;
+ Real off = period - on;
+
+ height = thick;
+ at = gh_list (ly_symbol2scm ("dashed-line"),
+ gh_double2scm (thick),
+ gh_double2scm (on),
+ gh_double2scm (off),
+ gh_double2scm (width),
+ SCM_UNDEFINED);
+ }
+ Box b (Interval (0, width), Interval (-height / 2, height / 2));
+ Molecule span (b, at);
+
+ Molecule m;
+ if (!edge[LEFT].empty_b ())
+ m = edge[LEFT];
+
+ if (!span.empty_b ())
+ m.add_at_edge (X_AXIS, RIGHT, span, 0);
+ if (!edge[RIGHT].empty_b ())
+ m.add_at_edge (X_AXIS, RIGHT, edge[RIGHT], 0);
+ m.translate_axis (broken_left, X_AXIS);
+
+ return m.create_scheme ();
+}
+
+
\consists "Output_property_engraver";
\consists "Dynamic_engraver"; % must come before text_engraver.
+ \consists "Text_spanner_engraver";
\consists "Property_engraver";
\consists "Breathing_sign_engraver";
(molecule-callback . ,Text_item::brew_molecule)
(no-spacing-rods . #t)
(interfaces . (text-script-interface text-item-interface side-position-interface))
- (padding . 3.0)
+ (padding . 0.5)
(name . "TextScript")
)
-
+ TextSpanner = #`(
+ (interfaces . (text-spanner-interface))
+ (molecule-callback . ,Text_spanner::brew_molecule)
+ (type . "line")
+ (direction . 1)
+ (text-style . "italic")
+ (name . "TextSpanner")
+ )
Tie = #`(
(interfaces . (tie-interface))
(molecule-callback . ,Tie::brew_molecule)
(name . "SustainPedal")
)
-
UnaChordaPdeal = #`(
(molecule-callback . ,Text_item::brew_molecule)
(style . "italic")
1 setlinecap
1 setlinejoin
setdash
+ dup
setlinewidth
- 0 0 moveto
+ 2 div
+ dup
+ 0 moveto
+ neg add
0 lineto
stroke
} bind def
(define (char i)
(string-append "\\char" (inexact->string i 10) " "))
- (define (dashed-line thick dash w)
- (embedded-ps ((ps-scm 'dashed-line) thick dash w)))
+ (define (dashed-line thick on off w)
+ (embedded-ps ((ps-scm 'dashed-line) thick on off w)))
(define (decrescendo thick w h cont)
(embedded-ps ((ps-scm 'decrescendo) thick w h cont)))
(number->string (* 10 thick)) ;UGH. 10 ?
" ] 0 draw_dashed_slur"))
- (define (dashed-line thick dash width)
+ (define (dashed-line thick on off width)
(string-append
(number->string width)
" "
(number->string thick)
" [ "
- (number->string dash)
+ (number->string on)
" "
- (number->string dash)
+ (number->string off)
" ] 0 draw_dashed_line"))
(define (decrescendo thick w h cont)