+1.3.111.jcn1
+============
+
+* Added simple glissando line.
+
+* Bugfix: broken [crescendo] text spanner.
+
1.3.110.hwn1
============
@lilypondfile{dyn-line.ly}
-Arpeggios are supported, both cross-staff and one-staff.
+Arpeggios are supported, both cross-staff and broken single staff.
@lilypondfile{arpeggio.ly}
+Simple glissando lines between notes are supported.
+
+@lilypondfile{glissando.ly}
+
@section Chord names
MAJOR_VERSION=1
MINOR_VERSION=3
PATCH_LEVEL=111
-MY_PATCH_LEVEL=
+MY_PATCH_LEVEL=jcn1
# use the above to send patches: MY_PATCH_LEVEL is always empty for a
# released version.
a1\fff\> \!a\pp
a\< \!a
\property Voice.crescendoText = "cresc."
-\property Voice.crescendoSpanner = "dashed-line"
+\property Voice.crescendoSpanner = #'dashed-line
a\mf\< a \!a
a\< \!a
}
--- /dev/null
+\score{
+ <
+ \context Staff=one \notes\relative c''{
+ a \glissando e'
+ % test: link thread to other staff
+ a, \glissando
+ \translator Staff=two
+ a,,
+ }
+ \context Staff=two { \clef bass; \skip 1; }
+ >
+ \paper{
+ linewidth = 70.\mm;
+ }
+}
\ No newline at end of file
\score{
\notes\relative c'''{
\property Voice.TextSpanner \revert #'type
- \property Voice.TextSpanner \override #'type = #"dotted-line"
+ \property Voice.TextSpanner \override #'type = #'dotted-line
\property Voice.TextSpanner \override #'edge-height = #'(0 . 1.5)
\property Voice.TextSpanner \override #'edge-text = #'("8va " . "")
\property Staff.centralCPosition = #-13
a \spanrequest \stop "text"
\property Voice.TextSpanner \revert #'type
- \property Voice.TextSpanner \override #'type = #"dotted-line"
+ \property Voice.TextSpanner \override #'type = #'dotted-line
a \spanrequest \start "text"
b c
a \spanrequest \stop "text"
\property Voice.TextSpanner \revert #'type
- \property Voice.TextSpanner \override #'type = #"dashed-line"
+ \property Voice.TextSpanner \override #'type = #'dashed-line
\property Voice.TextSpanner \override #'edge-height = #'(1 . -2)
a \spanrequest \start "text"
b c
return gh_reverse (removed);
}
-SCM
-ly_last (SCM list)
-{
- return gh_car (scm_last_pair (list));
-}
-
/* tail add */
SCM
ly_snoc (SCM s, SCM list)
Duration *r = (Duration *) gh_cdr (s);
scm_puts ("#<Duration ", port);
- scm_display (gh_str02scm ((char*)r->str().ch_C()), port);
+ scm_display (ly_str02scm (r->str().ch_C()), port);
scm_puts (" >", port);
return 1;
ugh. Use push/pop?
*/
SCM s = get_property ((start_type + "Spanner").ch_C());
- if (!gh_string_p (s) || ly_scm2string (s) == "hairpin")
+ if (!gh_symbol_p (s) || s == ly_symbol2scm ("hairpin"))
{
cresc_p_ = new Spanner (get_property ("Crescendo"));
cresc_p_->set_grob_property ("grow-direction",
warning (_("couldn't find any font satisfying ") );
scm_write (gh_list (name, point_sz, shape, series , family, rel_sz, SCM_UNDEFINED), scm_current_error_port ());
- return gh_str02scm ("cmr10");
+ return ly_str02scm ("cmr10");
}
A ly_B2A (B b);
*/
+
+SCM ly_last (SCM list);
SCM ly_str02scm (char const*c);
SCM ly_deep_copy (SCM);
SCM ly_symbol2scm (char const *);
class Font_metric;
class Font_size_engraver;
class Global_translator;
+class Glissando_req;
class Gourlay_breaking;
class Grace_engraver_group;
class Grace_iterator;
--- /dev/null
+/*
+ line-spanner.hh -- declare Line_spanner
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2000 Jan Nieuwenhuizen <janneke@gnu.org>
+*/
+
+
+#ifndef LINE_SPANNER_HH
+#define LINE_SPANNER_HH
+
+#include "lily-guile.hh"
+
+class Line_spanner
+{
+public:
+ DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM));
+ static SCM line_atom (Grob* me, Real dx, Real dy);
+};
+
+#endif /* LINE_SPANNER_HH */
VIRTUAL_COPY_CONS (Music);
};
+class Glissando_req : public Request
+{
+ VIRTUAL_COPY_CONS (Music);
+};
+
#endif // MUSICALREQUESTS_HH
#include "offset.hh"
#include "interval.hh"
+SCM
+ly_last (SCM list)
+{
+ return gh_car (scm_last_pair (list));
+}
+
SCM
ly_str02scm (char const*c)
{
SCM
ly_parse_scm (char const* s, int* n)
{
- SCM str = gh_str02scm ((char*)s);
+ SCM str = ly_str02scm (s);
SCM port = scm_mkstrport (SCM_INUM0, str, SCM_OPN | SCM_RDNG,
"ly_eval_scm_0str");
SCM from = scm_ftell (port);
sprintf (str, "%d ", gh_scm2int (s));
}
- return gh_str02scm (str);
+ return ly_str02scm (str);
}
/*
--- /dev/null
+/*
+ line-spanner.cc -- implement Line_spanner
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2000 Jan Nieuwenhuizen <janneke@gnu.org>
+*/
+
+#include "molecule.hh"
+#include "item.hh"
+#include "spanner.hh"
+#include "line-spanner.hh"
+#include "paper-def.hh"
+#include "paper-column.hh"
+#include "staff-symbol-referencer.hh"
+
+SCM
+Line_spanner::line_atom (Grob* me, Real dx, Real dy)
+{
+ SCM list = SCM_EOL;
+ SCM type = me->get_grob_property ("type");
+ if (gh_symbol_p (type)
+ && (type == ly_symbol2scm ("line")
+ || type == ly_symbol2scm ("dashed-line")
+ || type == ly_symbol2scm ("dotted-line")))
+ {
+ Real staff_space = Staff_symbol_referencer::staff_space (me);
+ Real thick = me->paper_l ()->get_var ("stafflinethickness");
+
+ SCM s = me->get_grob_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_grob_property ("dash-length");
+ if (gh_number_p (s))
+ length = gh_scm2double (s) * staff_space;
+
+ Real period = 2 * length + thick;
+ s = me->get_grob_property ("dash-period");
+ if (gh_number_p (s))
+ period = gh_scm2double (s) * staff_space;
+
+ if (type == ly_symbol2scm ("dotted-line"))
+ length = thick;
+
+ if (type == ly_symbol2scm ("line"))
+ length = period + thick;
+
+ Real on = length - thick;
+ Real off = period - on;
+
+ list = gh_list (ly_symbol2scm ("dashed-line"),
+ gh_double2scm (thick),
+ gh_double2scm (on),
+ gh_double2scm (off),
+ gh_double2scm (dx),
+ gh_double2scm (dy),
+ SCM_UNDEFINED);
+ }
+ return list;
+}
+
+
+MAKE_SCHEME_CALLBACK (Line_spanner, brew_molecule, 1);
+SCM
+Line_spanner::brew_molecule (SCM smob)
+{
+ Grob *me= unsmob_grob (smob);
+ Spanner *spanner = dynamic_cast<Spanner*> (me);
+
+ Grob *common[] = { 0, 0 };
+ common[X_AXIS] = spanner->get_bound (LEFT)->common_refpoint (spanner->get_bound (RIGHT), X_AXIS);
+ common[Y_AXIS] = spanner->get_bound (LEFT)->common_refpoint (spanner->get_bound (RIGHT), Y_AXIS);
+
+ if (!common[X_AXIS] || !common[Y_AXIS])
+ return SCM_EOL;
+
+ Real dx =
+ spanner->get_bound (LEFT)->relative_coordinate (common[X_AXIS], X_AXIS)
+ - spanner->get_bound (RIGHT)->relative_coordinate (common[X_AXIS], X_AXIS)
+ + spanner->get_bound (RIGHT)->extent (spanner->get_bound (RIGHT),
+ X_AXIS)[LEFT]
+ - spanner->get_bound (LEFT)->extent (spanner->get_bound (LEFT),
+ X_AXIS)[RIGHT];
+
+ Real dy =
+ spanner->get_bound (LEFT)->relative_coordinate (common[Y_AXIS], Y_AXIS)
+ - spanner->get_bound (RIGHT)->relative_coordinate (common[Y_AXIS], Y_AXIS)
+ + spanner->get_bound (RIGHT)->extent (spanner->get_bound (RIGHT),
+ Y_AXIS).center ()
+ - spanner->get_bound (LEFT)->extent (spanner->get_bound (LEFT),
+ Y_AXIS).center ();
+
+ Molecule line;
+ Real gap = gh_scm2double (me->get_grob_property ("gap"));
+ Offset o (dx, dy);
+ o *= (o.length () - 2 * gap) / o.length ();
+
+ SCM list = Line_spanner::line_atom (me, o[X_AXIS], o[Y_AXIS]);
+
+ if (list == SCM_EOL)
+ return SCM_EOL;
+
+ Box b (Interval (0, o[X_AXIS]), Interval (0, o[Y_AXIS]));
+
+ line = Molecule (b, list);
+ line.translate_axis (spanner->get_bound (LEFT)->extent (spanner->get_bound (LEFT), X_AXIS).length (), X_AXIS);
+ Offset g = o * (gap / o.length ());
+ line.translate (g);
+
+ return line.smobbed_copy ();
+}
+
+
Global_translator *
Music_output_def::get_global_translator_p ()
{
- Translator_def * t = unsmob_translator_def (find_translator_l (gh_str02scm ("Score")));
+ Translator_def * t = unsmob_translator_def (find_translator_l (ly_str02scm ("Score")));
if (!t)
error (_f ("can't find `%s' context", "Score"));
{"elementdescriptions", ELEMENTDESCRIPTIONS},
{"font", FONT},
{"grace", GRACE},
+ {"glissando", GLISSANDO},
{"header", HEADER},
{"in", IN_T},
{"lyrics", LYRICS},
--- /dev/null
+/*
+ note-head-line-engraver.cc -- implement Note_head_line_engraver
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2000 Jan Nieuwenhuizen <janneke@gnu.org>
+ */
+
+#include "engraver.hh"
+#include "group-interface.hh"
+#include "item.hh"
+#include "musical-request.hh"
+#include "spanner.hh"
+#include "rhythmic-head.hh"
+#include "side-position-interface.hh"
+#include "staff-symbol-referencer.hh"
+#include "protected-scm.hh"
+
+/**
+ Create line-spanner grobs for glissandi (and possibly other) lines
+ that connect note heads.
+ */
+
+class Note_head_line_engraver : public Engraver
+{
+public:
+ VIRTUAL_COPY_CONS (Translator);
+ Note_head_line_engraver ();
+
+protected:
+ virtual void acknowledge_grob (Grob_info);
+ virtual void create_grobs ();
+ virtual void stop_translation_timestep ();
+ virtual bool try_music (Music *);
+
+private:
+ Spanner* line_;
+ Request* req_;
+ Protected_scm heads_;
+};
+
+Note_head_line_engraver::Note_head_line_engraver ()
+{
+ line_ = 0;
+ req_ = 0;
+ heads_ = SCM_EOL;
+}
+
+bool
+Note_head_line_engraver::try_music (Music* m)
+{
+ if (!req_)
+ {
+ if (Glissando_req *r = dynamic_cast<Glissando_req*> (m))
+ {
+ req_ = r;
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+Note_head_line_engraver::acknowledge_grob (Grob_info info)
+{
+ if (req_)
+ {
+ if (Rhythmic_head::has_interface (info.elem_l_))
+ {
+ heads_ = gh_cons (info.elem_l_->self_scm (), heads_);
+ }
+ }
+}
+
+void
+Note_head_line_engraver::create_grobs ()
+{
+ if (!line_ && scm_ilength (heads_) > 1)
+ {
+ /* type Glissando? */
+ line_ = new Spanner (get_property ("NoteHeadLine"));
+ line_->set_bound (LEFT, unsmob_grob (gh_car (heads_)));
+ line_->set_bound (RIGHT, unsmob_grob (ly_last (heads_)));
+
+ line_->set_parent (unsmob_grob (gh_car (heads_)), X_AXIS);
+ line_->set_parent (unsmob_grob (gh_car (heads_)), Y_AXIS);
+
+ line_->set_parent (unsmob_grob (ly_last (heads_)), X_AXIS);
+ line_->set_parent (unsmob_grob (ly_last (heads_)), Y_AXIS);
+
+ announce_grob (line_, req_);
+ req_ = 0;
+ heads_ = SCM_EOL;
+ }
+}
+
+void
+Note_head_line_engraver::stop_translation_timestep ()
+{
+ if (line_)
+ {
+ typeset_grob (line_);
+ line_ = 0;
+ }
+}
+
+
+ADD_THIS_TRANSLATOR (Note_head_line_engraver);
+
%token DURATION
%token EXTENDER
%token FONT
+%token GLISSANDO
%token GRACE
%token HEADER
%token HYPHEN
a->set_spot (THIS->here_input ());
$$ = a;
}
+ | GLISSANDO {
+ Glissando_req *g = new Glissando_req;
+ g->set_spot /* No pun intended */ (THIS->here_input ());
+ $$ = g;
+ }
;
sup_quotes:
Pitch *r = (Pitch *) gh_cdr (s);
scm_puts ("#<Pitch ", port);
- scm_display (gh_str02scm ((char*)r->str().ch_C()), port);
+ scm_display (ly_str02scm (r->str().ch_C()), port);
scm_puts (" >", port);
return 1;
#include "molecule.hh"
#include "text-item.hh"
#include "text-spanner.hh"
+#include "line-spanner.hh"
#include "spanner.hh"
#include "font-interface.hh"
#include "dimensions.hh"
Spanner *spanner = dynamic_cast<Spanner*> (me);
Real staff_space = Staff_symbol_referencer::staff_space (me);
- Real thickness = 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 ());
+ if (s && s->musical_b ())
+ broken[d] = false;
+ else
+ broken[d] = true;
}
while (flip (&d) != LEFT);
-#if 0
- SCM s = me->get_grob_property ("text-style");
-
- String text_style = "italic";
- if (gh_string_p (s))
- text_style = ly_scm2string (s);
-#endif
-
SCM properties = Font_interface::font_alist_chain (me);
SCM edge_text = me->get_grob_property ("edge-text");
width = 0;
}
-
- String type = "dashed-line";
- s = me->get_grob_property ("type");
- if (gh_string_p (s))
- type = ly_scm2string (s);
-
+ /* ugh */
+ Real thick = me->paper_l ()->get_var ("stafflinethickness");
+
Molecule line;
- Drul_array<Molecule> edge_line;
- if (type == "line"
- || type == "dashed-line"
- || type == "dotted-line")
+ SCM list = Line_spanner::line_atom (me, width, 0);
+ if (list != SCM_EOL)
{
- Real thick = thickness;
- s = me->get_grob_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_grob_property ("dash-length");
- if (gh_number_p (s))
- length = gh_scm2double (s) * staff_space;
-
- Real period = 2 * length + thick;
- s = me->get_grob_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;
-
- SCM list = gh_list (ly_symbol2scm ("dashed-line"),
- gh_double2scm (thick),
- gh_double2scm (on),
- gh_double2scm (off),
- gh_double2scm (width),
- gh_double2scm (0),
- SCM_UNDEFINED);
-
Box b (Interval (0, width), Interval (-thick / 2, thick / 2));
line = Molecule (b, list);
-
- s = me->get_grob_property ("edge-height");
- if (gh_pair_p (s))
+ }
+
+ Drul_array<Molecule> edge_line;
+ s = me->get_grob_property ("edge-height");
+ if (gh_pair_p (s))
+ {
+ Direction d = LEFT;
+ int dir = to_dir (me->get_grob_property ("direction"));
+ do
{
- Direction d = LEFT;
- int dir = to_dir (me->get_grob_property ("direction"));
- do
+ Real dy = gh_scm2double (index_cell (s, d)) * - dir;
+ if (dy)
{
- Real dy = gh_scm2double (index_cell (s, d)) * - dir;
- if (dy)
- {
- SCM list = gh_list (ly_symbol2scm ("dashed-line"),
- gh_double2scm (thick),
- gh_double2scm (on),
- gh_double2scm (off),
- gh_double2scm (0),
- gh_double2scm (dy),
- SCM_UNDEFINED);
-
- Box b (Interval (0, thick),
- dy > 0
- ? Interval (0, dy)
- : Interval (dy, 0));
- edge_line[d] = Molecule (b, list);
- }
+ SCM list = Line_spanner::line_atom (me, 0, dy);
+ Box b (Interval (0, thick),
+ dy > 0
+ ? Interval (0, dy)
+ : Interval (dy, 0));
+ edge_line[d] = Molecule (b, list);
}
- while (flip (&d) != LEFT);
}
+ while (flip (&d) != LEFT);
}
-
+
Molecule m;
if (!edge[LEFT].empty_b ())
m = edge[LEFT];
\type Engraver_group_engraver;
\consists "Thread_devnull_engraver";
\consists "Note_heads_engraver";
+ \consists "Note_head_line_engraver";
\consists "Output_property_engraver";
Generic_property_list = #generic-thread-properties
\consists "Property_engraver";
print only if there is no beam associated with this tuplet bracket.")
(elt-property-description 'tuplet-number-visibility boolean-or-symbol? "
Like @code{tuplet-bracket-visibility}, but for the number.")
-(elt-property-description 'type string? "one of: line, dashed-line or dotted-line")
+(elt-property-description 'type symbol? "one of: line, dashed-line or dotted-line")
(elt-property-description 'vertical-position-quant-function procedure? "
function of type (beam multiplicity dy staff-line-thickness) -> real. Default value: default-beam-y-quants, also available: beam-traditional-y-quants.
")
rhythmic-head-interface font-interface
note-head-interface ))
))
+ (NoteHeadLine . (
+ (type . line)
+ (gap . 0.5)
+ (molecule-callback . ,Line_spanner::brew_molecule)
+ (meta . ,(element-description "NoteHeadLine"
+ line-spanner-interface))
+ ))
(NoteName . (
(molecule-callback . ,Text_item::brew_molecule)
(define generic-notename-properties
(cons 'note-name-interface
- (list (list 'noteNaemStyle symbol? 'style))))
+ (list (list 'noteNameStyle symbol? 'style))))
(define generic-rest-properties
)))
+(define line-spanner-interface
+ (lily-interface
+ 'line-spanner-interface
+ "generic line spanner"
+ '(
+ dash-period
+ dash-length
+ line-thickness
+ type
+ )
+ ))
+
(define lyric-hyphen-interface
(lily-interface
'lyric-hyphen-interface