From c0198cfd7fc1ad742c54afdfd5e2f943fa923dbd Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Mon, 26 Sep 2005 23:25:59 +0000 Subject: [PATCH] * lily/paper-system.cc (read_left_bound): new function. Read line-break-system-details from left bound to determine extents. * Documentation/user/programming-interface.itely (Using LilyPond syntax inside Scheme): change applyxxx -> applyXxx. * ly/music-functions-init.ly: add outputProperty music function. * lily/parser.yy (Generic_prefix_music_scm): add scm-scm-scm signature. * lily/grob-scheme.cc (LY_DEFINE): add ! to ly:grob-suicide! name. * python/convertrules.py (conv): rule * ly/music-functions-init.ly: applyxxx -> applyXxx * ly/engraver-init.ly (AncientRemoveEmptyStaffContext): alias TabVoice to Voice. --- ChangeLog | 21 ++++++++ Documentation/user/advanced-notation.itely | 4 +- Documentation/user/invoking.itely | 2 +- .../user/programming-interface.itely | 36 ++++++------- lily/grob-scheme.cc | 2 +- lily/include/paper-system.hh | 3 +- lily/lexer.ll | 6 ++- lily/paper-book.cc | 1 + lily/paper-column-engraver.cc | 10 +++- lily/paper-column.cc | 52 +++++++++++-------- lily/paper-system-scheme.cc | 2 +- lily/paper-system.cc | 40 +++++++++++++- lily/parser.yy | 4 ++ lily/score-engraver.cc | 15 ++++-- lily/system.cc | 6 +-- ly/engraver-init.ly | 1 + ly/music-functions-init.ly | 23 ++++++-- python/convertrules.py | 11 ++++ scm/define-grob-properties.scm | 4 ++ scm/safe-lily.scm | 2 +- 20 files changed, 181 insertions(+), 64 deletions(-) diff --git a/ChangeLog b/ChangeLog index 94c266c6f2..c899dfbf3c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2005-09-27 Han-Wen Nienhuys + + * lily/paper-system.cc (read_left_bound): new function. Read + line-break-system-details from left bound to determine extents. + + * Documentation/user/programming-interface.itely (Using LilyPond + syntax inside Scheme): change applyxxx -> applyXxx. + + * ly/music-functions-init.ly: add outputProperty music function. + + * lily/parser.yy (Generic_prefix_music_scm): add scm-scm-scm signature. + + * lily/grob-scheme.cc (LY_DEFINE): add ! to ly:grob-suicide! name. + + * python/convertrules.py (conv): rule + + * ly/music-functions-init.ly: applyxxx -> applyXxx + + * ly/engraver-init.ly (AncientRemoveEmptyStaffContext): alias + TabVoice to Voice. + 2005-09-26 Han-Wen Nienhuys * flower/include/real.hh: include iso. diff --git a/Documentation/user/advanced-notation.itely b/Documentation/user/advanced-notation.itely index 9d4a2e62f4..0b0a8fb977 100644 --- a/Documentation/user/advanced-notation.itely +++ b/Documentation/user/advanced-notation.itely @@ -1899,7 +1899,7 @@ The following example demonstrates its use. @lilypond[quote,verbatim,fragment,raggedright,relative=2] \context Voice { - \applyoutput + \applyOutput #(add-balloon-text 'NoteHead "heads, or tails?" '(1 . -3)) c8 @@ -2321,7 +2321,7 @@ problematic notes. @cindex automatic beams, tuning @cindex tuning automatic beaming -@c [TODO: use \applycontext] +@c [TODO: use \applyContext] In normal time signatures, automatic beams can start on any note but can only end in a few positions within the measure: beams can end on a beat, diff --git a/Documentation/user/invoking.itely b/Documentation/user/invoking.itely index fed9a894f2..e698d13a3a 100644 --- a/Documentation/user/invoking.itely +++ b/Documentation/user/invoking.itely @@ -488,7 +488,7 @@ here for reference. \magnify isn't changed to \fontsize. - \magnify #m => \fontsize #f, where f = 6ln(m)/ln(2) remove-tag isn't changed. - - \applymusic #(remove-tag '. . .) => \keepWithTag #'. . . + - \applyMusic #(remove-tag '. . .) => \keepWithTag #'. . . firstpagenumber isn't changed. - firstpagenumber no => printfirstpagenumber = ##f Line breaks in header strings aren't converted. diff --git a/Documentation/user/programming-interface.itely b/Documentation/user/programming-interface.itely index da209bcfd8..b5058b609b 100644 --- a/Documentation/user/programming-interface.itely +++ b/Documentation/user/programming-interface.itely @@ -161,11 +161,11 @@ The syntax of composite music expressions, like @code{\repeat}, Such syntax can also be defined as user code. To do this, it is necessary to create a @emph{music function}. This is a specially marked -Scheme function. For example, the music function @code{\applymusic} applies +Scheme function. For example, the music function @code{\applyMusic} applies a user-defined function to a music expression. Its syntax is @example -\applymusic #@var{func} @var{music} +\applyMusic #@var{func} @var{music} @end example A music function is created with @code{ly:make-music-function}, @@ -174,7 +174,7 @@ A music function is created with @code{ly:make-music-function}, (ly:make-music-function @end example -@code{\applymusic} takes a Scheme function and a Music expression as +@code{\applyMusic} takes a Scheme function and a Music expression as arguments. This is encoded in its parameter list, @example @@ -192,10 +192,10 @@ and line numbers. The definition is the second argument of @end example The above Scheme code only defines the functionality. The tag -@code{\applymusic} is selected by defining +@code{\applyMusic} is selected by defining @example -applymusic = #(ly:make-music-function +applyMusic = #(ly:make-music-function (list procedure? ly:music?) (lambda (parser location func music) (func music))) @@ -206,12 +206,12 @@ A @code{def-music-function} macro is introduced on top of functions: @example -applymusic = #(def-music-function (parser location func music) +applyMusic = #(def-music-function (parser location func music) (procedure? ly:music?) (func music)) @end example -Examples of the use of @code{\applymusic} are in the next section. +Examples of the use of @code{\applyMusic} are in the next section. @seealso @file{ly/@/music@/-functions@/-init@/.ly}. @@ -220,10 +220,10 @@ Examples of the use of @code{\applymusic} are in the next section. @subsection Manipulating music expressions Music objects and their properties can be accessed and manipulated -directly, through the @code{\applymusic} mechanism. -The syntax for @code{\applymusic} is +directly, through the @code{\applyMusic} mechanism. +The syntax for @code{\applyMusic} is @example -\applymusic #@var{func} @var{music} +\applyMusic #@var{func} @var{music} @end example @noindent @@ -241,7 +241,7 @@ its argument, (reverse (ly:music-property m 'elements))) m) -\applymusic #rev-music-1 { c'4 d'4 } +\applyMusic #rev-music-1 { c'4 d'4 } @end lilypond The use of such a function is very limited. The effect of this @@ -249,13 +249,13 @@ function is void when applied to an argument that does not have multiple children. The following function application has no effect @example -\applymusic #rev-music-1 \grace @{ c4 d4 @} +\applyMusic #rev-music-1 \grace @{ c4 d4 @} @end example @noindent In this case, @code{\grace} is stored as @internalsref{GraceMusic}, which has no @code{elements}, only a single @code{element}. Every generally -applicable function for @code{\applymusic} must -- like music expressions +applicable function for @code{\applyMusic} must -- like music expressions themselves -- be recursive. The following example is such a recursive function: It first extracts @@ -295,7 +295,7 @@ above by the internal equivalent of \context Voice = "2" @{ \voiceTwo b @} >> @end example -Other applications of @code{\applymusic} are writing out repeats +Other applications of @code{\applyMusic} are writing out repeats automatically (@inputfileref{input/@/test,unfold@/-all@/-repeats@/.ly}), saving keystrokes (@inputfileref{input/@/test,music@/-box@/.ly}) and exporting LilyPond input to other formats @@ -402,7 +402,7 @@ example: { c'^"1" - \applymusic #(with-padding 3) { c'^"2" c'^"3" } + \applyMusic #(with-padding 3) { c'^"2" c'^"3" } c'^"4" } @end lilypond @@ -720,12 +720,12 @@ to the @code{interpret-markup} function, with the @code{layout} and @subsection Context evaluation @cindex calling code during interpreting -@cindex @code{\applycontext} +@cindex @code{\applyContext} Contexts can be modified during interpretation with Scheme code. The syntax for this is @example -\applycontext @var{function} +\applyContext @var{function} @end example @var{function} should be a Scheme function taking a single argument, @@ -733,7 +733,7 @@ being the context to apply it to. The following code will print the current bar number on the standard output during the compile: @example -\applycontext +\applyContext #(lambda (x) (format #t "\nWe were called in barnumber ~a.\n" (ly:context-property x 'currentBarNumber))) diff --git a/lily/grob-scheme.cc b/lily/grob-scheme.cc index 4480d4f990..972fd0bfc7 100644 --- a/lily/grob-scheme.cc +++ b/lily/grob-scheme.cc @@ -186,7 +186,7 @@ LY_DEFINE (ly_spanner_broken_into, "ly:spanner-broken-into", return s; } -LY_DEFINE (ly_grob_suicide, "ly:grob-suicide", +LY_DEFINE (ly_grob_suicide_x, "ly:grob-suicide!", 1, 0, 0, (SCM g), "Kill @var{g}.") { diff --git a/lily/include/paper-system.hh b/lily/include/paper-system.hh index 3c9168993e..c292d96413 100644 --- a/lily/include/paper-system.hh +++ b/lily/include/paper-system.hh @@ -29,11 +29,12 @@ public: int number_; Paper_system (Stencil, bool); - + void read_left_bound (Item*); Stencil to_stencil () const; SCM stencils () const; bool is_title () const; Real break_before_penalty () const; + Interval staff_refpoints () const; }; DECLARE_UNSMOB (Paper_system, paper_system); diff --git a/lily/lexer.ll b/lily/lexer.ll index a5fbdb6a94..d12fea5936 100644 --- a/lily/lexer.ll +++ b/lily/lexer.ll @@ -518,7 +518,7 @@ BOM_UTF8 \357\273\277 else if (tag == ly_symbol2scm ("scheme0-scheme1-scheme2")) return MARKUP_HEAD_SCM0_SCM1_SCM2; else { - programming_error ("no parser tag defined for this signature"); + programming_error ("no parser tag defined for this markup signature"); ly_display_scm (s); assert(false); } @@ -920,6 +920,10 @@ music_function_type (SCM func) { return MUSIC_FUNCTION_SCM_SCM_MUSIC; } + else if (type == ly_symbol2scm ("scm-scm-scm")) + { + return MUSIC_FUNCTION_SCM_SCM_SCM; + } else if (type == ly_symbol2scm ("markup")) { return MUSIC_FUNCTION_MARKUP; diff --git a/lily/paper-book.cc b/lily/paper-book.cc index 77ac4fff8a..2294a0aef8 100644 --- a/lily/paper-book.cc +++ b/lily/paper-book.cc @@ -321,6 +321,7 @@ Paper_book::systems () Paper_system *ps = new Paper_system (*unsmob_stencil (t), true); systems_ = scm_cons (ps->self_scm (), systems_); ps->unprotect (); + // FIXME: figure out penalty. //set_system_penalty (ps, scores_[i].header_); } diff --git a/lily/paper-column-engraver.cc b/lily/paper-column-engraver.cc index 256aa430b9..efc9226d83 100644 --- a/lily/paper-column-engraver.cc +++ b/lily/paper-column-engraver.cc @@ -214,7 +214,13 @@ ADD_TRANSLATOR (Paper_column_engraver, "Score_engraver::forbid_breaks to stop linebreaks. In practice, this " "means that you can make a breakpoint by creating a barline (assuming " "that there are no beams or notes that prevent a breakpoint.) ", - /* create */ "PaperColumn NonMusicalPaperColumn", + + /* create */ + "PaperColumn " + "NonMusicalPaperColumn", + /* accept */ "break-event", /* read */ "", - /* write */ "currentCommandColumn currentMusicalColumn"); + /* write */ + "currentCommandColumn " + "currentMusicalColumn"); diff --git a/lily/paper-column.cc b/lily/paper-column.cc index ce29a2011a..13407f61e0 100644 --- a/lily/paper-column.cc +++ b/lily/paper-column.cc @@ -26,29 +26,6 @@ Paper_column::clone (int count) const return new Paper_column (*this, count); } -ADD_INTERFACE (Paper_column, "paper-column-interface", - "@code{Paper_column} objects form the top-most X-parents for items." - " The are two types of columns: musical columns, where are attached to, and " - " non-musical columns, where bar-lines, clefs etc. are attached to. " - " The spacing engine determines the X-positions of these objects." - - "\n\n" - "They are\n" - " numbered, the first (leftmost) is column 0. Numbering happens before\n" - " line-breaking, and columns are not renumbered after line breaking.\n" - " Since many columns go unused, you should only use the rank field to\n" - " get ordering information. Two adjacent columns may have\n" - " non-adjacent numbers.\n", - - - "between-cols " - "bounded-by-me " - "page-penalty " - "shortest-playing-duration " - "shortest-starter-duration " - "used " - "when "); - void Paper_column::do_break_processing () { @@ -194,3 +171,32 @@ Paper_column::before_line_breaking (SCM grob) return SCM_UNSPECIFIED; } + + +ADD_INTERFACE (Paper_column, + + "paper-column-interface", + "@code{Paper_column} objects form the top-most X-parents for items." + " The are two types of columns: musical columns, where are attached to, and " + " non-musical columns, where bar-lines, clefs etc. are attached to. " + " The spacing engine determines the X-positions of these objects." + + "\n\n" + "They are\n" + " numbered, the first (leftmost) is column 0. Numbering happens before\n" + " line-breaking, and columns are not renumbered after line breaking.\n" + " Since many columns go unused, you should only use the rank field to\n" + " get ordering information. Two adjacent columns may have\n" + " non-adjacent numbers.\n", + + + /* properties */ + "between-cols " + "bounded-by-me " + "line-break-system-details " + "page-penalty " + "shortest-playing-duration " + "shortest-starter-duration " + "used " + "when "); + diff --git a/lily/paper-system-scheme.cc b/lily/paper-system-scheme.cc index 760999b3eb..97bb947afe 100644 --- a/lily/paper-system-scheme.cc +++ b/lily/paper-system-scheme.cc @@ -61,6 +61,6 @@ LY_DEFINE (ly_paper_system_staff_extent, "ly:paper-system-staff-extents", { Paper_system *ps = unsmob_paper_system (system); SCM_ASSERT_TYPE (ps, system, SCM_ARG1, __FUNCTION__, "paper-system"); - return ly_interval2scm (ps->staff_refpoints_); + return ly_interval2scm (ps->staff_refpoints ()); } diff --git a/lily/paper-system.cc b/lily/paper-system.cc index e78a1e9be9..5f5e1702c9 100644 --- a/lily/paper-system.cc +++ b/lily/paper-system.cc @@ -7,8 +7,7 @@ */ #include "paper-system.hh" - -#include "virtual-methods.hh" +#include "item.hh" #include "ly-smobs.icc" @@ -70,3 +69,40 @@ Paper_system::to_stencil () const { return stencil_; } + +void +Paper_system::read_left_bound (Item *left) +{ + break_before_penalty_ + = robust_scm2double (left->get_property ("page-penalty"), 0.0); + + SCM details + = left->get_property ("line-break-system-details"); + + SCM yext + = scm_assoc (ly_symbol2scm ("Y-extent"), details); + + SCM staff_ext + = scm_assoc (ly_symbol2scm ("refpoint-Y-extent"), details); + + if (scm_is_pair (yext) + && is_number_pair (scm_cdr (yext))) + { + Box b = stencil_.extent_box(); + b[Y_AXIS] = ly_scm2interval (scm_cdr (yext)); + + stencil_ = Stencil (b, stencil_.expr ()); + } + + if (scm_is_pair (staff_ext) + && is_number_pair (scm_cdr (staff_ext))) + { + staff_refpoints_ = ly_scm2interval (scm_cdr (staff_ext)); + } +} + +Interval +Paper_system::staff_refpoints () const +{ + return staff_refpoints_; +} diff --git a/lily/parser.yy b/lily/parser.yy index 475e556ace..0b71a7f5db 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -407,6 +407,7 @@ parser.yy:352.8-24: warning: symbol `"\\<"' used more than once as a literal str %token MUSIC_FUNCTION_SCM_MUSIC_MUSIC %token MUSIC_FUNCTION_SCM_SCM %token MUSIC_FUNCTION_SCM_SCM_MUSIC +%token MUSIC_FUNCTION_SCM_SCM_SCM %token MUSIC_IDENTIFIER %token NOTENAME_PITCH %token NUMBER_IDENTIFIER @@ -1116,6 +1117,9 @@ Generic_prefix_music_scm: | MUSIC_FUNCTION_SCM_SCM embedded_scm embedded_scm { $$ = scm_list_4 ($1, make_input (@$), $2, $3); } + | MUSIC_FUNCTION_SCM_SCM_SCM embedded_scm embedded_scm embedded_scm { + $$ = scm_list_5 ($1, make_input (@$), $2, $3, $4); + } | MUSIC_FUNCTION_SCM_SCM_MUSIC embedded_scm embedded_scm Music { $$ = scm_list_5 ($1, make_input (@$), $2, $3, $4->self_scm ()); } diff --git a/lily/score-engraver.cc b/lily/score-engraver.cc index 44e7a9e427..281416068c 100644 --- a/lily/score-engraver.cc +++ b/lily/score-engraver.cc @@ -169,7 +169,14 @@ ADD_TRANSLATOR_GROUP (Score_engraver, "Score_engraver::forbid_breaks to stop linebreaks. In practice, this " "means that you can make a breakpoint by creating a barline (assuming " "that there are no beams or notes that prevent a breakpoint.) ", - /* create */ "System PaperColumn NonMusicalPaperColumn", - /* accept */ "break-event", - /* read */ "currentMusicalColumn currentCommandColumn verticallySpacedContexts", - /* write */ ""); + /* create */ + "System ", + + /* accept */ + "break-event", + /* read */ + "currentMusicalColumn " + "currentCommandColumn " + "verticallySpacedContexts", + /* write */ + ""); diff --git a/lily/system.cc b/lily/system.cc index 6e597b1bf3..7df79c196c 100644 --- a/lily/system.cc +++ b/lily/system.cc @@ -385,10 +385,8 @@ System::get_paper_system () Paper_system *pl = new Paper_system (sys_stencil, false); pl->staff_refpoints_ = staff_refpoints; - Item *break_point = this->get_bound (LEFT); - pl->break_before_penalty_ - = robust_scm2double (break_point->get_property ("page-penalty"), 0.0); - + pl->read_left_bound (this->get_bound (LEFT)); + return pl->unprotect (); } diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly index 5d8ba62dc2..eca683aeba 100644 --- a/ly/engraver-init.ly +++ b/ly/engraver-init.ly @@ -616,6 +616,7 @@ AncientRemoveEmptyStaffContext = \context { \context { \Voice \name "TabVoice" + \alias "Voice" \consists "Tab_note_heads_engraver" \remove "Note_heads_engraver" \remove "Fingering_engraver" diff --git a/ly/music-functions-init.ly b/ly/music-functions-init.ly index 18297e98ab..d32a540f76 100644 --- a/ly/music-functions-init.ly +++ b/ly/music-functions-init.ly @@ -6,7 +6,7 @@ #(use-modules (srfi srfi-1)) -applymusic = +applyMusic = #(def-music-function (parser location func music) (procedure? ly:music?) (func music)) @@ -33,7 +33,7 @@ autochange = #(def-music-function (parser location music) (ly:music?) (make-autochange-music music)) -applycontext = +applyContext = #(def-music-function (parser location proc) (procedure?) (make-music 'ApplyContext 'origin location @@ -58,12 +58,29 @@ displayLilyMusic = (display-lily-music music) music) -applyoutput = +applyOutput = #(def-music-function (parser location proc) (procedure?) (make-music 'ApplyOutputEvent 'origin location 'procedure proc)) +outputProperty = +#(def-music-function (parser location name prop value) + (symbol? symbol? scheme?) + + + "Set @var{prop} to @var{value} in all grobs named @var{name} " + + (make-music 'ApplyOutputEvent + 'origin location + 'procedure + (lambda (grob orig-context context) + (if (equal? + (cdr (assoc 'name (ly:grob-property grob 'meta))) + name) + (set! (ly:grob-property grob prop) value) + )))) + breathe = #(def-music-function (parser location) () (make-music 'EventChord diff --git a/python/convertrules.py b/python/convertrules.py index 6f99647b16..471a4927b4 100644 --- a/python/convertrules.py +++ b/python/convertrules.py @@ -2555,3 +2555,14 @@ conversions.append (((2, 7, 6), conv, '''Performer_group_performer -> Performer_group, Engraver_group_engraver -> Engraver_group inside-slur -> avoid-slur''')) + + +def conv (str): + str = re.sub(r'\\applyoutput', '\\applyOutput', str) + str = re.sub(r'\\applycontext', '\\applyContext', str) + str = re.sub(r'\\applymusic', '\\applyMusic', str) + str = re.sub(r'ly:grob-suicide', 'ly:grob-suicide!', str) + return str + +conversions.append (((2, 7, 10), conv, + '''\\applyxxx -> \\applyXxx''')) diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index 7628772368..f71ee578c7 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -306,6 +306,10 @@ unbeamed stems.") (length-fraction ,number? "Length of ledger line as fraction of note head size.") (lengths ,list? "Default stem lengths. The list gives a length for each flag-count.") + (line-break-system-details ,list? + "Alist of properties to use when this +column is the start of a system.") + (line-count ,integer? "The number of staff lines.") (measure-length ,ly:moment? "Length of a measure. Used in some spacing situations.") diff --git a/scm/safe-lily.scm b/scm/safe-lily.scm index e9310f6aed..9300f8b248 100644 --- a/scm/safe-lily.scm +++ b/scm/safe-lily.scm @@ -56,7 +56,7 @@ ly:grob-script-priority-less ly:grob-set-property! ly:grob-staff-position - ly:grob-suicide + ly:grob-suicide! ly:grob-system ly:grob-translate-axis! ly:grob? -- 2.39.2