summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Puttock <n.puttock@gmail.com>2011-02-13 23:32:12 +0000
committerNeil Puttock <n.puttock@gmail.com>2011-02-13 23:32:12 +0000
commitf40beee2bdf96ff578b5a3d004cc276ee333b799 (patch)
tree86a84f58e1afc294a9848ea2dc9aed8770cc012c
parent90fcc649dc06ad006158945acc15a69e24e942cd (diff)
Better support for beat slashes (multi-slash & mixed duration).
* input/regression/repeat-slash-mixed.ly, repeat-slash-multi.ly: new regtests * lily/context.cc (check_repeat_count_visibility): add repeat count visibility proc for use in percent repeat engravers * lily/double-percent-repeat-engraver.cc (new file): create separate engraver for double-measure percent repeats, which listens to DoublePercentEvent * lily/percent-repeat-engraver.cc: listen to PercentEvent and create single-measure repeats only * lily/percent-repeat-item.cc: (brew_slash, brew_slash): add count arg to set number of slashes read slash-count from event-cause * lily/percent-repeat-iterator.cc (get_music_list): send separate synthetic events for percent, double-percent and beat repeats use measure length to choose between full-measure types call scheme proc to get slash count for beat repeats * lily/slash-repeat-engraver.cc: listen to RepeatSlashEvent and use slash-count to switch between RepeatSlash and DoublePercentRepeat * ly/engraver-init.ly: add Double_percent_repeat_engraver to Voice context * scm/define-event-classes.scm (event-classes): add new classes (double-percent-event/repeat-slash-event) * scm/define-grobs.scm (all-grob-descriptions): add DoubleRepeatSlash set slash-negative-kern in RepeatSlash (required for multi-slash beat repeats) * scm/define-music-properties.scm (all-music-properties): doc slash-count * scm/define-music-types.scm (music-descriptions): add synthetic events DoublePercentEvent and RepeatSlashEvent * scm/music-functions.scm (calc-repeat-slash-count): new function used by Percent_repeat_iterator to check durations; returns either number of slashes (if all durations equal) or 0 (if durations vary)
-rw-r--r--input/regression/repeat-slash-mixed.ly18
-rw-r--r--input/regression/repeat-slash-multi.ly11
-rw-r--r--lily/context.cc10
-rw-r--r--lily/double-percent-repeat-engraver.cc113
-rw-r--r--lily/include/context.hh4
-rw-r--r--lily/include/percent-repeat-item.hh2
-rw-r--r--lily/multi-measure-rest.cc1
-rw-r--r--lily/percent-repeat-engraver.cc181
-rw-r--r--lily/percent-repeat-item.cc36
-rw-r--r--lily/percent-repeat-iterator.cc27
-rw-r--r--lily/slash-repeat-engraver.cc40
-rw-r--r--ly/engraver-init.ly1
-rw-r--r--scm/define-event-classes.scm5
-rw-r--r--scm/define-grobs.scm16
-rw-r--r--scm/define-music-properties.scm2
-rw-r--r--scm/define-music-types.scm12
-rw-r--r--scm/music-functions.scm32
17 files changed, 326 insertions, 185 deletions
diff --git a/input/regression/repeat-slash-mixed.ly b/input/regression/repeat-slash-mixed.ly
new file mode 100644
index 0000000000..a474504443
--- /dev/null
+++ b/input/regression/repeat-slash-mixed.ly
@@ -0,0 +1,18 @@
+\version "2.13.51"
+
+\header {
+ texidoc = "Beat repeats for patterns containing mixed durations use
+a double percent symbol."
+}
+
+\relative c' {
+ \repeat percent 4 {
+ c8. <d f>16
+ }
+ \repeat percent 2 {
+ \times 2/3 {
+ r8 d e
+ }
+ c4
+ }
+}
diff --git a/input/regression/repeat-slash-multi.ly b/input/regression/repeat-slash-multi.ly
new file mode 100644
index 0000000000..dd670402d3
--- /dev/null
+++ b/input/regression/repeat-slash-multi.ly
@@ -0,0 +1,11 @@
+\version "2.13.51"
+
+\header {
+ texidoc = "Beat repeats for patterns containing identical durations
+shorter than an eighth note use multiple slashes."
+}
+
+\relative c' {
+ \repeat percent 2 { c16 d e f }
+ \repeat percent 4 { c32 e g e }
+}
diff --git a/lily/context.cc b/lily/context.cc
index 5dd6cf10ba..4dbb6e5657 100644
--- a/lily/context.cc
+++ b/lily/context.cc
@@ -772,3 +772,13 @@ melisma_busy (Context *tr)
return busy;
}
+
+bool
+check_repeat_count_visibility (Context const *context, SCM count)
+{
+ SCM proc = context->get_property ("repeatCountVisibility");
+ return (ly_is_procedure (proc)
+ && to_boolean (scm_call_2 (proc,
+ count,
+ context->self_scm ())));
+}
diff --git a/lily/double-percent-repeat-engraver.cc b/lily/double-percent-repeat-engraver.cc
new file mode 100644
index 0000000000..ad64657e97
--- /dev/null
+++ b/lily/double-percent-repeat-engraver.cc
@@ -0,0 +1,113 @@
+/*
+ This file is part of LilyPond, the GNU music typesetter.
+
+ Copyright (C) 2011 Neil Puttock <n.puttock@gmail.com>
+
+ LilyPond is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ LilyPond is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "engraver.hh"
+#include "global-context.hh"
+#include "international.hh"
+#include "item.hh"
+#include "side-position-interface.hh"
+#include "stream-event.hh"
+#include "warn.hh"
+
+#include "translator.icc"
+
+class Double_percent_repeat_engraver : public Engraver
+{
+public:
+ TRANSLATOR_DECLARATIONS (Double_percent_repeat_engraver);
+
+protected:
+ Stream_event *percent_event_;
+
+ // moment (global time) where percent started
+ Moment start_mom_;
+
+ DECLARE_TRANSLATOR_LISTENER (double_percent);
+
+ void process_music ();
+};
+
+Double_percent_repeat_engraver::Double_percent_repeat_engraver ()
+{
+ percent_event_ = 0;
+}
+
+IMPLEMENT_TRANSLATOR_LISTENER (Double_percent_repeat_engraver, double_percent);
+void
+Double_percent_repeat_engraver::listen_double_percent (Stream_event *ev)
+{
+ if (!percent_event_)
+ {
+ Moment meas_len (robust_scm2moment (get_property ("measureLength"),
+ Moment (1)));
+ start_mom_ = now_mom () + meas_len;
+ get_global_context ()->add_moment_to_process (start_mom_);
+ percent_event_ = ev;
+ }
+ else
+ ASSIGN_EVENT_ONCE (percent_event_, ev);
+}
+
+void
+Double_percent_repeat_engraver::process_music ()
+{
+ if (percent_event_ && now_mom ().main_part_ == start_mom_.main_part_)
+ {
+ Item *double_percent = make_item ("DoublePercentRepeat",
+ percent_event_->self_scm ());
+
+ SCM count = percent_event_->get_property ("repeat-count");
+ if (count != SCM_EOL && to_boolean (get_property ("countPercentRepeats"))
+ && check_repeat_count_visibility (context (), count))
+ {
+ Item *double_percent_counter
+ = make_item ("DoublePercentRepeatCounter",
+ percent_event_->self_scm ());
+
+ SCM text = scm_number_to_string (count, scm_from_int (10));
+ double_percent_counter->set_property ("text", text);
+
+ Side_position_interface::add_support (double_percent_counter,
+ double_percent);
+ double_percent_counter->set_parent (double_percent, Y_AXIS);
+ double_percent_counter->set_parent (double_percent, X_AXIS);
+ }
+ // forbid breaks on a % line
+ context ()->get_score_context ()->set_property ("forbidBreak",
+ SCM_BOOL_T);
+ percent_event_ = 0;
+ }
+}
+
+ADD_TRANSLATOR (Double_percent_repeat_engraver,
+ /* doc */
+ "Make double measure repeats.",
+
+ /* create */
+ "DoublePercentRepeat "
+ "DoublePercentRepeatCounter ",
+
+ /* read */
+ "countPercentRepeats "
+ "measureLength "
+ "repeatCountVisibility ",
+
+ /* write */
+ "forbidBreak "
+ );
diff --git a/lily/include/context.hh b/lily/include/context.hh
index 3806c957e8..4121f84c78 100644
--- a/lily/include/context.hh
+++ b/lily/include/context.hh
@@ -154,6 +154,9 @@ Moment measure_position (Context const *context);
Moment measure_position (Context const *context, Duration const *dur);
Rational measure_length (Context const *context);
int measure_number (Context const *context);
+
+bool check_repeat_count_visibility (Context const *context, SCM count);
+
void set_context_property_on_children (Context *trans, SCM sym, SCM val);
/* Shorthand for creating and broadcasting stream events. */
@@ -168,4 +171,3 @@ SCM nested_property_revert_alist (SCM alist, SCM prop_path);
SCM evict_from_alist (SCM, SCM, SCM);
#endif /* CONTEXT_HH */
-
diff --git a/lily/include/percent-repeat-item.hh b/lily/include/percent-repeat-item.hh
index 1bc02fe155..a9e59e35f5 100644
--- a/lily/include/percent-repeat-item.hh
+++ b/lily/include/percent-repeat-item.hh
@@ -30,7 +30,7 @@ public:
DECLARE_SCHEME_CALLBACK (beat_slash, (SCM));
DECLARE_SCHEME_CALLBACK (double_percent, (SCM));
static Stencil x_percent (Grob *, int);
- static Stencil brew_slash (Grob *);
+ static Stencil brew_slash (Grob *, int);
};
#endif /* PERCENT_REPEAT_ITEM_HH */
diff --git a/lily/multi-measure-rest.cc b/lily/multi-measure-rest.cc
index 60b5c03c66..9628402a5e 100644
--- a/lily/multi-measure-rest.cc
+++ b/lily/multi-measure-rest.cc
@@ -63,6 +63,7 @@ Multi_measure_rest::percent (SCM smob)
Spanner *sp = dynamic_cast<Spanner *> (me);
Stencil r = Percent_repeat_item_interface::x_percent (me, 1);
+ r.translate_axis (-r.extent (X_AXIS).center (), X_AXIS);
// ugh copy & paste.
diff --git a/lily/percent-repeat-engraver.cc b/lily/percent-repeat-engraver.cc
index 5757f8b8ab..1b437b2822 100644
--- a/lily/percent-repeat-engraver.cc
+++ b/lily/percent-repeat-engraver.cc
@@ -18,14 +18,10 @@
*/
-#include "score-engraver.hh"
-
-#include "bar-line.hh"
+#include "engraver.hh"
#include "global-context.hh"
#include "international.hh"
#include "item.hh"
-#include "misc.hh"
-#include "repeated-music.hh"
#include "side-position-interface.hh"
#include "spanner.hh"
#include "stream-event.hh"
@@ -33,46 +29,32 @@
#include "translator.icc"
-/*
-* TODO: Create separate Double_percent_repeat_engraver?
-* Or, at least move double percent handling to Slash_repeat_engraver
-*/
-
class Percent_repeat_engraver : public Engraver
{
void typeset_perc ();
- bool check_count_visibility (SCM count);
+
public:
TRANSLATOR_DECLARATIONS (Percent_repeat_engraver);
protected:
Stream_event *percent_event_;
- /// moment (global time) where percent started.
- Moment stop_mom_;
+ // moment (global time) where percent started
Moment start_mom_;
-
- enum Repeat_sign_type
- {
- UNKNOWN,
- MEASURE,
- DOUBLE_MEASURE,
- };
- Repeat_sign_type repeat_sign_type_;
+ // moment (global time) where percent should end
+ Moment stop_mom_;
Spanner *percent_;
Spanner *percent_counter_;
-
Grob *first_command_column_;
Moment command_moment_;
-
-protected:
+
virtual void finalize ();
DECLARE_TRANSLATOR_LISTENER (percent);
- void stop_translation_timestep ();
void start_translation_timestep ();
+ void stop_translation_timestep ();
void process_music ();
};
@@ -91,7 +73,8 @@ Percent_repeat_engraver::start_translation_timestep ()
{
if (now_mom ().main_part_ != command_moment_.main_part_)
{
- first_command_column_ = unsmob_grob (get_property ("currentCommandColumn"));
+ first_command_column_
+ = unsmob_grob (get_property ("currentCommandColumn"));
command_moment_ = now_mom ();
}
@@ -100,7 +83,6 @@ Percent_repeat_engraver::start_translation_timestep ()
if (percent_)
typeset_perc ();
percent_event_ = 0;
- repeat_sign_type_ = UNKNOWN;
}
}
@@ -111,97 +93,50 @@ Percent_repeat_engraver::listen_percent (Stream_event *ev)
if (!percent_event_)
{
Moment body_length = get_event_length (ev);
- Moment meas_len (robust_scm2moment (get_property ("measureLength"),
- Moment (1)));
- if (meas_len == body_length)
- {
- repeat_sign_type_ = MEASURE;
- start_mom_ = now_mom ();
- stop_mom_ = now_mom () + body_length;
- get_global_context ()->add_moment_to_process (stop_mom_);
- }
- else if (Moment (2) * meas_len == body_length)
- {
- repeat_sign_type_ = DOUBLE_MEASURE;
- start_mom_ = now_mom () + meas_len;
- stop_mom_ = now_mom () + body_length; /* never used */
- get_global_context ()->add_moment_to_process (start_mom_);
- }
- else
- {
- /*
- don't warn about percent repeats: slash repeats are not
- exactly 1 or 2 measures long.
- */
- return;
- }
+ start_mom_ = now_mom ();
+ stop_mom_ = now_mom () + body_length;
+ get_global_context ()->add_moment_to_process (stop_mom_);
percent_event_ = ev;
}
else
- /* print a warning: no assignment happens because
- percent_event_ != 0 */
- ASSIGN_EVENT_ONCE (percent_event_, ev);
+ {
+ /*
+ print a warning: no assignment happens because
+ percent_event_ != 0
+ */
+ ASSIGN_EVENT_ONCE (percent_event_, ev);
+ }
}
void
Percent_repeat_engraver::process_music ()
{
- if (percent_event_ && now_mom ().main_part_ == start_mom_.main_part_)
+ if (percent_event_
+ && now_mom ().main_part_ == start_mom_.main_part_)
{
- if (repeat_sign_type_ == MEASURE)
- {
- if (percent_)
- typeset_perc ();
-
- percent_ = make_spanner ("PercentRepeat", percent_event_->self_scm ());
-
- Grob *col = first_command_column_;
- percent_->set_bound (LEFT, col);
-
- SCM count = percent_event_->get_property ("repeat-count");
- if (count != SCM_EOL && to_boolean (get_property ("countPercentRepeats"))
- && check_count_visibility (count))
- {
- percent_counter_
- = make_spanner ("PercentRepeatCounter", percent_event_->self_scm ());
-
- SCM text = scm_number_to_string (count, scm_from_int (10));
- percent_counter_->set_property ("text", text);
- percent_counter_->set_bound (LEFT, col);
- Side_position_interface::add_support (percent_counter_,
- percent_);
- percent_counter_->set_parent (percent_, Y_AXIS);
- }
- else
- percent_counter_ = 0;
- }
- else if (repeat_sign_type_ == DOUBLE_MEASURE)
+ if (percent_)
+ typeset_perc ();
+
+ percent_ = make_spanner ("PercentRepeat", percent_event_->self_scm ());
+
+ Grob *col = first_command_column_;
+ percent_->set_bound (LEFT, col);
+
+ SCM count = percent_event_->get_property ("repeat-count");
+ if (count != SCM_EOL && to_boolean (get_property ("countPercentRepeats"))
+ && check_repeat_count_visibility (context (), count))
{
- Item *double_percent = make_item ("DoublePercentRepeat", percent_event_->self_scm ());
-
- SCM count = percent_event_->get_property ("repeat-count");
- if (count != SCM_EOL && to_boolean (get_property ("countPercentRepeats"))
- && check_count_visibility (count))
- {
- Item *double_percent_counter = make_item ("DoublePercentRepeatCounter",
- percent_event_->self_scm ());
-
- SCM text = scm_number_to_string (count,
- scm_from_int (10));
- double_percent_counter->set_property ("text", text);
-
- Side_position_interface::add_support (double_percent_counter,
- double_percent);
- double_percent_counter->set_parent (double_percent, Y_AXIS);
- double_percent_counter->set_parent (double_percent, X_AXIS);
- }
-
- /* forbid breaks on a % line. Should forbid all breaks, really. */
- context ()->get_score_context ()->set_property ("forbidBreak", SCM_BOOL_T);
-
- /* No more processing needed. */
- repeat_sign_type_ = UNKNOWN;
+ percent_counter_ = make_spanner ("PercentRepeatCounter",
+ percent_event_->self_scm ());
+
+ SCM text = scm_number_to_string (count, scm_from_int (10));
+ percent_counter_->set_property ("text", text);
+ percent_counter_->set_bound (LEFT, col);
+ Side_position_interface::add_support (percent_counter_, percent_);
+ percent_counter_->set_parent (percent_, Y_AXIS);
}
+ else
+ percent_counter_ = 0;
}
}
@@ -219,29 +154,16 @@ Percent_repeat_engraver::finalize ()
void
Percent_repeat_engraver::typeset_perc ()
{
- if (percent_)
- {
- Grob *col = first_command_column_;
+ Grob *col = first_command_column_;
- percent_->set_bound (RIGHT, col);
- percent_ = 0;
-
- if (percent_counter_)
- percent_counter_->set_bound (RIGHT, col);
- percent_counter_ = 0;
- }
-}
+ percent_->set_bound (RIGHT, col);
+ percent_ = 0;
-bool
-Percent_repeat_engraver::check_count_visibility (SCM count)
-{
- SCM proc = get_property ("repeatCountVisibility");
- return (ly_is_procedure (proc) && to_boolean (scm_call_2 (proc,
- count,
- context ()->self_scm ())));
+ if (percent_counter_)
+ percent_counter_->set_bound (RIGHT, col);
+ percent_counter_ = 0;
}
-
void
Percent_repeat_engraver::stop_translation_timestep ()
{
@@ -249,20 +171,17 @@ Percent_repeat_engraver::stop_translation_timestep ()
ADD_TRANSLATOR (Percent_repeat_engraver,
/* doc */
- "Make whole bar and double bar repeats.",
+ "Make whole measure repeats.",
/* create */
- "DoublePercentRepeat "
- "DoublePercentRepeatCounter "
"PercentRepeat "
"PercentRepeatCounter ",
/* read */
"countPercentRepeats "
"currentCommandColumn "
- "measureLength "
"repeatCountVisibility ",
/* write */
- "forbidBreak "
+ ""
);
diff --git a/lily/percent-repeat-item.cc b/lily/percent-repeat-item.cc
index 337df45058..1e97753fee 100644
--- a/lily/percent-repeat-item.cc
+++ b/lily/percent-repeat-item.cc
@@ -18,12 +18,14 @@
*/
#include "percent-repeat-item.hh"
+
#include "item.hh"
-#include "lookup.hh"
#include "font-interface.hh"
+#include "lookup.hh"
+#include "stream-event.hh"
Stencil
-Percent_repeat_item_interface::brew_slash (Grob *me)
+Percent_repeat_item_interface::brew_slash (Grob *me, int count)
{
Real slope = robust_scm2double (me->get_property ("slope"), 1);
Real wid = 2.0 / slope;
@@ -32,7 +34,14 @@ Percent_repeat_item_interface::brew_slash (Grob *me)
todo: check out if in staff-rule thickness normally.
*/
Real thick = robust_scm2double (me->get_property ("thickness"), 1);
- Stencil m = Lookup::repeat_slash (wid, slope, thick);
+ Stencil slash = Lookup::repeat_slash (wid, slope, thick);
+ Stencil m = slash;
+
+ Real slash_neg_kern =
+ robust_scm2double (me->get_property ("slash-negative-kern"), 1.6);
+ for (int i = count - 1; i--;)
+ m.add_at_edge (X_AXIS, RIGHT, slash, -slash_neg_kern);
+
m.translate_axis (-m.extent (Y_AXIS).center (), Y_AXIS);
return m;
}
@@ -40,16 +49,11 @@ Percent_repeat_item_interface::brew_slash (Grob *me)
Stencil
Percent_repeat_item_interface::x_percent (Grob *me, int count)
{
- Stencil m;
- Stencil s = brew_slash (me);
+ Stencil m = brew_slash (me, count);
Real dot_neg_kern =
robust_scm2double (me->get_property ("dot-negative-kern"), 0.75);
- Real slash_neg_kern =
- robust_scm2double (me->get_property ("slash-negative-kern"), 1.6);
- for (int i = count; i--;)
- m.add_at_edge (X_AXIS, RIGHT, s, -slash_neg_kern);
Stencil d1 = Font_interface::get_default_font (me)->find_by_name ("dots.dot");
Stencil d2 = d1;
d1.translate_axis (0.5, Y_AXIS);
@@ -58,7 +62,6 @@ Percent_repeat_item_interface::x_percent (Grob *me, int count)
m.add_at_edge (X_AXIS, LEFT, d1, -dot_neg_kern);
m.add_at_edge (X_AXIS, RIGHT, d2, -dot_neg_kern);
- m.translate_axis (- m.extent (X_AXIS).center (), X_AXIS);
return m;
}
@@ -68,6 +71,7 @@ Percent_repeat_item_interface::double_percent (SCM grob)
{
Grob *me = unsmob_grob (grob);
Stencil m = x_percent (me, 2);
+ m.translate_axis (-m.extent (X_AXIS).center (), X_AXIS);
return m.smobbed_copy ();
}
@@ -76,18 +80,24 @@ SCM
Percent_repeat_item_interface::beat_slash (SCM grob)
{
Grob *me = unsmob_grob (grob);
- Stencil m = brew_slash (me);
+ Stream_event *cause = unsmob_stream_event (me->get_property ("cause"));
+ int count = robust_scm2int (cause->get_property ("slash-count"), 1);
+
+ Stencil m;
+ if (count == 0)
+ m = x_percent (me, 2);
+ else
+ m = brew_slash (me, count);
return m.smobbed_copy ();
}
ADD_INTERFACE (Percent_repeat_item_interface,
"Repeats that look like percent signs.",
-
+
/* properties */
"dot-negative-kern "
"slash-negative-kern "
"slope "
"thickness "
);
-
diff --git a/lily/percent-repeat-iterator.cc b/lily/percent-repeat-iterator.cc
index 845bd729b6..d829553557 100644
--- a/lily/percent-repeat-iterator.cc
+++ b/lily/percent-repeat-iterator.cc
@@ -18,6 +18,7 @@
along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "context.hh"
#include "input.hh"
#include "repeated-music.hh"
#include "sequential-iterator.hh"
@@ -41,20 +42,40 @@ Percent_repeat_iterator::Percent_repeat_iterator ()
SCM
Percent_repeat_iterator::get_music_list () const
{
- /* TODO: Distinction between percent, double-percent and slash */
Music *mus = get_music ();
Music *child = Repeated_music::body (mus);
SCM length = child->get_length ().smobbed_copy ();
SCM child_list = SCM_EOL;
+ Moment measure_len = measure_length (get_outlet ());
+ Moment music_len = robust_scm2moment (length, Moment (0));
+
+ string event_type;
+ SCM slash_count = SCM_EOL;
+
+ if (measure_len == music_len)
+ event_type = "PercentEvent";
+ else if (measure_len * Moment (2) == music_len)
+ event_type = "DoublePercentEvent";
+ else
+ {
+ slash_count
+ = scm_call_1 (ly_lily_module_constant ("calc-repeat-slash-count"),
+ child->self_scm ());
+ event_type = "RepeatSlashEvent";
+ }
int repeats = scm_to_int (mus->get_property ("repeat-count"));
for (int i = repeats; i > 1; i--)
{
- Music *percent = make_music_by_name (ly_symbol2scm ("PercentEvent"));
+ Music *percent = make_music_by_name (ly_symbol2scm (event_type.c_str ()));
percent->set_spot (*mus->origin ());
percent->set_property ("length", length);
if (repeats > 1)
- percent->set_property ("repeat-count", scm_from_int (i));
+ {
+ percent->set_property ("repeat-count", scm_from_int (i));
+ if (event_type == "RepeatSlashEvent")
+ percent->set_property ("slash-count", slash_count);
+ }
child_list = scm_cons (percent->unprotect (), child_list);
}
diff --git a/lily/slash-repeat-engraver.cc b/lily/slash-repeat-engraver.cc
index 26a64f9380..0db3ceffb3 100644
--- a/lily/slash-repeat-engraver.cc
+++ b/lily/slash-repeat-engraver.cc
@@ -18,22 +18,15 @@
along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "bar-line.hh"
-#include "global-context.hh"
-#include "international.hh"
#include "item.hh"
-#include "misc.hh"
-#include "repeated-music.hh"
-#include "score-engraver.hh"
-#include "spanner.hh"
+#include "engraver.hh"
#include "stream-event.hh"
-#include "warn.hh"
#include "translator.icc"
-/**
- This acknowledges repeated music with "percent" style. It typesets
- a slash sign.
+/*
+ This acknowledges repeated music with "percent" style. It typesets
+ a slash sign or double percent sign.
*/
class Slash_repeat_engraver : public Engraver
{
@@ -42,7 +35,7 @@ public:
protected:
Stream_event *slash_;
protected:
- DECLARE_TRANSLATOR_LISTENER (percent);
+ DECLARE_TRANSLATOR_LISTENER (repeat_slash);
void process_music ();
};
@@ -51,21 +44,11 @@ Slash_repeat_engraver::Slash_repeat_engraver ()
slash_ = 0;
}
-IMPLEMENT_TRANSLATOR_LISTENER (Slash_repeat_engraver, percent);
+IMPLEMENT_TRANSLATOR_LISTENER (Slash_repeat_engraver, repeat_slash);
void
-Slash_repeat_engraver::listen_percent (Stream_event *ev)
+Slash_repeat_engraver::listen_repeat_slash (Stream_event *ev)
{
- /*todo: separate events for percent and slash */
- Moment meas_length
- = robust_scm2moment (get_property ("measureLength"), Moment (0));
-
- if (get_event_length (ev) < meas_length)
ASSIGN_EVENT_ONCE (slash_, ev);
-
- /*
- don't warn if nothing happens: this can happen if there are whole
- measure repeats.
- */
}
void
@@ -73,7 +56,11 @@ Slash_repeat_engraver::process_music ()
{
if (slash_)
{
- make_item ("RepeatSlash", slash_->self_scm ());
+ SCM count = slash_->get_property ("slash-count");
+ if (scm_to_int (count) == 0)
+ make_item ("DoubleRepeatSlash", slash_->self_scm ());
+ else
+ make_item ("RepeatSlash", slash_->self_scm ());
slash_ = 0;
}
}
@@ -83,10 +70,11 @@ ADD_TRANSLATOR (Slash_repeat_engraver,
"Make beat repeats.",
/* create */
+ "DoubleRepeatSlash "
"RepeatSlash ",
/* read */
- "measureLength ",
+ "",
/* write */
""
diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly
index 92c8398f34..28c7c9706f 100644
--- a/ly/engraver-init.ly
+++ b/ly/engraver-init.ly
@@ -243,6 +243,7 @@ multiple voices on the same staff."
\consists "New_fingering_engraver"
\consists "Chord_tremolo_engraver"
+ \consists "Double_percent_repeat_engraver"
\consists "Percent_repeat_engraver"
\consists "Slash_repeat_engraver"
\consists "Part_combine_engraver"
diff --git a/scm/define-event-classes.scm b/scm/define-event-classes.scm
index 539288b843..022ae640e1 100644
--- a/scm/define-event-classes.scm
+++ b/scm/define-event-classes.scm
@@ -50,8 +50,9 @@
(break-span-event . (break-dynamic-span-event))
(pedal-event . (sostenuto-event sustain-event una-corda-event))
(rhythmic-event . (lyric-event melodic-event multi-measure-rest-event
- percent-event
- rest-event skip-event bass-figure-event))
+ double-percent-event percent-event
+ repeat-slash-event rest-event
+ skip-event bass-figure-event))
(melodic-event . (cluster-note-event note-event))
(() . (Announcement))
(Announcement . (AnnounceNewContext))
diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm
index 59f756e8a0..92edba5f1d 100644
--- a/scm/define-grobs.scm
+++ b/scm/define-grobs.scm
@@ -667,7 +667,6 @@
(slope . 1.0)
(stencil . ,ly:percent-repeat-item-interface::double-percent)
(thickness . 0.48)
- (width . 2.0)
(meta . ((class . Item)
(interfaces . (break-aligned-interface
font-interface
@@ -699,6 +698,20 @@
side-position-interface
text-interface))))))
+ (DoubleRepeatSlash
+ . (
+ (dot-negative-kern . 0.75)
+ (font-encoding . fetaMusic)
+ (slash-negative-kern . 1.6)
+ (slope . 1.0)
+ (stencil . ,ly:percent-repeat-item-interface::beat-slash)
+ (thickness . 0.48)
+ (meta . ((class . Item)
+ (interfaces . (font-interface
+ percent-repeat-interface
+ percent-repeat-item-interface
+ rhythmic-grob-interface))))))
+
(DynamicLineSpanner
. (
(axes . (,Y))
@@ -1570,6 +1583,7 @@
(RepeatSlash
. (
+ (slash-negative-kern . 0.85)
(slope . 1.7)
(stencil . ,ly:percent-repeat-item-interface::beat-slash)
(thickness . 0.48)
diff --git a/scm/define-music-properties.scm b/scm/define-music-properties.scm
index b2db381b7e..b18a10f3ad 100644
--- a/scm/define-music-properties.scm
+++ b/scm/define-music-properties.scm
@@ -157,6 +157,8 @@ or down-stem?")
(repeat-count ,integer? "Do a @code{\\repeat} how often?")
+ (slash-count ,integer? "The number of slashes in a single-beat repeat.
+If zero, signals a beat containing varying durations.")
(span-direction ,ly:dir? "Does this start or stop a spanner?")
(span-type ,symbol? "What kind of dynamic spanner should be created?
Options are @code{'text} and @code{'hairpin}.")
diff --git a/scm/define-music-types.scm b/scm/define-music-types.scm
index 43b826e8b8..cdf5c0a6a1 100644
--- a/scm/define-music-types.scm
+++ b/scm/define-music-types.scm
@@ -175,6 +175,11 @@ An alternative syntax is @var{note}@code{\\decr} @dots{}
event))
))
+ (DoublePercentEvent
+ . ((description . "Used internally to signal double percent repeats.")
+ (types . (general-music event double-percent-event rhythmic-event))
+ ))
+
(EpisemaEvent
. ((description . "Begin or end an episema.")
(types . (general-music span-event event episema-event))
@@ -375,7 +380,7 @@ as separate voices.")
))
(PercentRepeatedMusic
- . ((description . "Repeats encoded by percents.")
+ . ((description . "Repeats encoded by percents and slashes.")
(iterator-ctor . ,ly:percent-repeat-iterator::constructor)
(start-callback . ,ly:repeated-music::first-start)
(length-callback . ,ly:repeated-music::unfolded-music-length)
@@ -450,6 +455,11 @@ Syntax: @code{\\unset @var{context}.@var{prop}}")
(types . (general-music repeated-music))
))
+ (RepeatSlashEvent
+ . ((description . "Used internally to signal beat repeats.")
+ (types . (general-music event repeat-slash-event rhythmic-event))
+ ))
+
(RepeatTieEvent
. ((description . "Ties for starting a second volta bracket.")
(types . (general-music event repeat-tie-event))
diff --git a/scm/music-functions.scm b/scm/music-functions.scm
index b015c536a6..ed96cfd8d2 100644
--- a/scm/music-functions.scm
+++ b/scm/music-functions.scm
@@ -301,6 +301,20 @@ through MUSIC."
(shift-duration-log r shift dots))
r)))
+(define (calc-repeat-slash-count music)
+ "Given the child-list @var{music} in @code{PercentRepeatMusic},
+calculate the number of slashes based on the durations. Returns @code{0}
+if durations in in @var{music} vary, allowing slash beats and double-percent
+beats to be distinguished."
+ (let* ((durs (map (lambda (elt)
+ (duration-of-note elt))
+ (extract-named-music music 'EventChord)))
+ (first-dur (car durs)))
+
+ (if (every (lambda (d) (equal? d first-dur)) durs)
+ (max (- (ly:duration-log first-dur) 2) 1)
+ 0)))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; clusters.
@@ -1385,14 +1399,20 @@ as a context."
skip))
(define-public (pitch-of-note event-chord)
+ (let ((evs (filter (lambda (x)
+ (music-has-type x 'note-event))
+ (ly:music-property event-chord 'elements))))
- (let*
- ((evs (filter (lambda (x) (memq 'note-event (ly:music-property x 'types)))
- (ly:music-property event-chord 'elements))))
+ (and (pair? evs)
+ (ly:music-property (car evs) 'pitch))))
+
+(define-public (duration-of-note event-chord)
+ (let ((evs (filter (lambda (x)
+ (music-has-type x 'rhythmic-event))
+ (ly:music-property event-chord 'elements))))
- (if (pair? evs)
- (ly:music-property (car evs) 'pitch)
- #f)))
+ (and (pair? evs)
+ (ly:music-property (car evs) 'duration))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;