From d6aeca26549bf677b085deb82c95ccc9d0646838 Mon Sep 17 00:00:00 2001 From: hanwen Date: Sun, 8 Feb 2004 23:14:30 +0000 Subject: [PATCH] (Lilypond_snippet.notice_include): write .dep file. --- ChangeLog | 33 +++ Documentation/bibliography/engraving.bib | 10 +- Documentation/user/appendices.itely | 2 +- Documentation/user/introduction.itely | 14 +- Documentation/user/refman.itely | 232 +++++++++++++++++- VERSION | 4 +- input/regression/lyric-hyphen-break.ly | 35 +++ input/test/lyric-hyphen-retain.ly | 49 ++++ lily/coherent-ligature-engraver.cc | 2 +- lily/hyphen-engraver.cc | 2 +- lily/hyphen-spanner.cc | 90 ------- .../{hyphen-spanner.hh => lyric-hyphen.hh} | 1 - lily/include/paper-column.hh | 10 +- lily/lyric-hyphen.cc | 116 +++++++++ lily/new-part-combine-iterator.cc | 1 + lily/paper-column.cc | 4 +- lily/system.cc | 2 +- ly/engraver-init.ly | 2 +- make/ly-rules.make | 2 +- scm/define-grobs.scm | 2 +- scripts/lilypond-book.py | 50 ++-- 21 files changed, 524 insertions(+), 139 deletions(-) create mode 100644 input/regression/lyric-hyphen-break.ly create mode 100644 input/test/lyric-hyphen-retain.ly delete mode 100644 lily/hyphen-spanner.cc rename lily/include/{hyphen-spanner.hh => lyric-hyphen.hh} (90%) create mode 100644 lily/lyric-hyphen.cc diff --git a/ChangeLog b/ChangeLog index 8542b0a12c..363f126d07 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2004-02-09 Han-Wen Nienhuys + + * scripts/lilypond-book.py (Lilypond_snippet.notice_include): + write .dep file. + +2004-02-08 Han-Wen Nienhuys + + * Documentation/user/refman.itely (Markup command definition): Doc + by Nicolas Sceaux. Rewrite by Han-Wen + + * lily/lyric-hyphen.cc (brew_molecule): remove if hyphen is first + thing of the line. + (brew_molecule): only remove if hyphen is not at the end of line. + (set_spacing_rods): new function: minimum-length specifies + distance between syllables. + + * scm/define-grobs.scm (all-grob-descriptions): add + Hyphen_spanner::set_spacing_rods to LyricHyphen + + * input/regression/lyric-hyphen-break.ly: new file. + + * input/test/lyric-hyphen-retain.ly: new file. + + * lily/new-part-combine-iterator.cc (construct_children): + add Rest direction. + +2004-02-08 Han-Wen Nienhuys + + * scripts/lilypond-book.py (Snippet.replacement_text): add method. + + * Documentation/bibliography/engraving.bib (donemus1982): + update entry. + 2004-02-07 Jan Nieuwenhuizen * scripts/lilypond.py (option_definitions): Fix typo. diff --git a/Documentation/bibliography/engraving.bib b/Documentation/bibliography/engraving.bib index b4383faa6e..0209a87ffd 100644 --- a/Documentation/bibliography/engraving.bib +++ b/Documentation/bibliography/engraving.bib @@ -192,11 +192,17 @@ of print. } note={Heussenstamm writes: Limited in scope, similar to \cite{Roemer84}} } -@Book {donemes1900, - year = {1900}, +@Book {donemus1982, + year = {1982}, title = {Uitgeven van muziek}, author = {Donemus}, publisher= {Donemus Amsterdam}, + + note = {Manual on copying for composers and copyists at the Dutch + publishing house Donemus. Besides general comments on copying, it + also contains a lot of hands-on advice for making performance + material for modern pieces.} + } diff --git a/Documentation/user/appendices.itely b/Documentation/user/appendices.itely index c648ac7a65..eb0229825d 100644 --- a/Documentation/user/appendices.itely +++ b/Documentation/user/appendices.itely @@ -12,7 +12,7 @@ @node Chord name chart @section Chord name chart -@lilypondfile[notexidoc]{chord-names-jazz.ly} +@lilypondfile{chord-names-jazz.ly} @node MIDI instruments @section MIDI instruments diff --git a/Documentation/user/introduction.itely b/Documentation/user/introduction.itely index 5e9af3ffb0..ae051f5720 100644 --- a/Documentation/user/introduction.itely +++ b/Documentation/user/introduction.itely @@ -63,7 +63,7 @@ analogy, each plug-in is also called @code{engraver}. In the following example, we see how we start out with a note head engraver. -@lilypond[notexidoc] +@lilypond[] \include "engraver-example.lyinc" \score { \topVoice @@ -93,7 +93,7 @@ engraver. Then a @code{Staff_symbol_engraver} adds the staff: -@lilypond[notexidoc] +@lilypond[] \include "engraver-example.lyinc" \score { \topVoice @@ -122,7 +122,7 @@ Then a @code{Staff_symbol_engraver} adds the staff: The @code{Clef_engraver} defines a reference point for the staff: -@lilypond[notexidoc] +@lilypond[] \include "engraver-example.lyinc" \score { \topVoice @@ -148,7 +148,7 @@ Then a @code{Staff_symbol_engraver} adds the staff: And the @code{Stem_engraver} adds stems: -@lilypond[notexidoc] +@lilypond[] \include "engraver-example.lyinc" \score { \topVoice @@ -178,7 +178,7 @@ By adding engravers for beams, slurs, accents, accidentals, bar lines, time signature, and key signature, we get a complete piece of notation. -@lilypond[notexidoc] +@lilypond[] \include "engraver-example.lyinc" \score { \topVoice } @@ -189,7 +189,7 @@ notation. This system works well for monophonic music, but what about polyphony? In polyphonic notation, many voices can share a staff. -@lilypond[notexidoc] +@lilypond[] \include "engraver-example.lyinc" \score { \context Staff << \topVoice \\ \botVoice >> } @end lilypond @@ -203,7 +203,7 @@ case of polyphony, a single Staff context contains more than one Voice context. In polyphonic notation, many voices can share a staff: Similarly, more Staff contexts can be put into a single Score context. -@lilypond[notexidoc] +@lilypond[] \include "engraver-example.lyinc" \score { << \new Staff << \topVoice \\ \botVoice >> diff --git a/Documentation/user/refman.itely b/Documentation/user/refman.itely index edab5ee2c3..2aa79478be 100644 --- a/Documentation/user/refman.itely +++ b/Documentation/user/refman.itely @@ -2030,7 +2030,7 @@ different characteristics of the performance. They are added to a note by adding a dash and the character signifying the articulation. They are demonstrated here: -@lilypondfile[notexidoc]{script-abbreviations.ly} +@lilypondfile[]{script-abbreviations.ly} The meanings of these shorthands can be changed: see @file{ly/script-init.ly} for examples. @@ -2083,7 +2083,7 @@ eg. @cindex coda @cindex varcoda -@lilypondfile[notexidoc]{script-chart.ly} +@lilypondfile[]{script-chart.ly} @refcommands @@ -3335,6 +3335,8 @@ next one. Such a line is called an extender line, and it is entered as Internals: @internalsref{LyricEvent}, @internalsref{HyphenEvent}, and @internalsref{ExtenderEvent}. +Examples: @inputfileref{input/test,lyric-hyphen-retain.ly} + @refbugs The definition of lyrics mode is too complex. @@ -3432,6 +3434,7 @@ in @inputfileref{input/regression,lyric-combine-new.ly}. A complete example of a SATB score setup is in the file @inputfileref{input/template,satb.ly}. + @refcommands @code{\melisma}, @code{\melismaEnd} @@ -4191,7 +4194,7 @@ beginning of each line. This is illustrated in the following example, whose source is available as @inputfileref{input/test,bar-number-regular-interval.ly}: -@lilypondfile[notexidoc]{bar-number-regular-interval.ly} +@lilypondfile[]{bar-number-regular-interval.ly} @seealso @@ -4569,7 +4572,7 @@ filtered. For example, @end example would yield -@lilypondfile[notexidoc]{tag-filter.ly} +@lilypondfile[]{tag-filter.ly} The argument of the @code{\tag} command should be a symbol, or a list of symbols, for example, @@ -5344,7 +5347,7 @@ and @code{\finalis} at proper places in the input. Some editions use Therefore, @code{gregorian-init.ly} also defines @code{\virgula} and @code{\caesura}: -@lilypondfile[notexidoc]{divisiones.ly} +@lilypondfile[]{divisiones.ly} @refcommands @@ -7347,7 +7350,7 @@ The following example (from @inputfileref{input/regression,cluster.ly}) shows what the result looks like: -@lilypondfile[notexidoc]{cluster.ly} +@lilypondfile[]{cluster.ly} By default, @internalsref{Cluster_spanner_engraver} is in the @internalsref{Voice} context. This allows putting ordinary notes and @@ -7530,6 +7533,7 @@ treatment of the difference between translation and layout. * Applyoutput:: * Font selection:: * Text markup:: +* Common text markup commands:: @end menu @@ -8063,6 +8067,14 @@ For clarity, you can also do this for single arguments, e.g. @cindex font size, texts + + + + +@node Common text markup commands +@subsection Common text markup commands + + The following size commands set absolute sizes: @cindex @code{\teeny} @@ -8232,9 +8244,6 @@ allegro = \markup { \bold \large { Allegro } } \notes { a^\allegro b c d } @end verbatim -The markup mechanism is extensible. Refer to -@file{scm/new-markup.scm} for more information. - Some objects have alignment procedures of their own, which cancel out any effects of alignments applied to their markup arguments as a @@ -8251,6 +8260,7 @@ all markup commands. Init files: @file{scm/new-markup.scm}. + @refbugs @cindex kerning @@ -8267,7 +8277,211 @@ field. Titles are made by La@TeX{}, so La@TeX{} commands should be used for formatting. +@menu +* Markup construction in scheme:: +* Markup command definition:: +@end menu + +@node Markup construction in scheme +@subsubsection Markup construction in scheme + +@cindex defining markup commands + +The @code{markup} macro builds markup expressions in Scheme while +providing a LilyPond-like syntax. For example, +@example +(markup #:column (#:line (#:bold #:italic "hello" #:raise 0.4 "world") + #:bigger #:line ("foo" "bar" "baz"))) +@end example + +@noindent +is equivalent to: +@example +\markup \column < @{ \bold \italic "hello" \raise #0.4 "world" @} + \bigger @{ foo bar baz @} > +@end example + +@noindent +This example exposes the main translation rules between regular +LilyPond markup syntax and scheme markup syntax, which are summed up +is this table: +@multitable @columnfractions .5 .5 +@item @b{LilyPond} @tab @b{Scheme} +@item @code{\command} @tab @code{#:command} +@item @code{\variable} @tab @code{variable} +@item @code{@{ ... @}} @tab @code{#:line ( ... )} +@item @code{\center < ... >} @tab @code{#:center ( ... )} +@item @code{string} @tab @code{"string"} +@item @code{#scheme-arg} @tab @code{scheme-arg} +@end multitable + +Besides, the whole scheme language is accessible inside the +@code{markup} macro: thus, one may use function calls inside +@code{markup} in order to manipulate character strings for +instance. This proves useful when defining new markup commands (see +@ref{Markup command definition}). + +@refbugs + +One can not feed the @code{#:line} (resp @code{#:center}, +@code{#:column}) command with a variable or the result of a function +call. Eg: +@lisp +(markup #:line (fun-that-returns-markups)) +@end lisp +is illegal. One should use the @code{make-line-markup} (resp +@code{make-center-markup}, @code{make-column-markup}) function +instead: +@lisp +(markup (make-line-markup (fun-that-returns-markups))) +@end lisp + +@node Markup command definition +@subsubsection Markup command definition + +New markup commands can be defined thanks to the @code{def-markup-command} scheme macro. +@lisp +(def-markup-command (@emph{command-name} @emph{paper} @emph{props} @emph{arg1} @emph{arg2} ...) (@emph{arg1-type?} @emph{arg2-type?} ...) + ..command body..) + + @emph{argi}: i@emph{th} command argument + @emph{argi-type?}: a type predicate for the i@emph{th} argument + @emph{paper}: the `paper' definition + @emph{props}: a list of alists, containing all active properties. +@end lisp + +As a simple example, we show how to add a @code{\smallcaps} command, +which selects @TeX{}'s small caps font. Normally, we could select the +small caps font as follows: + +@verbatim + \markup { \override #'(font-shape . caps) Text-in-caps } +@end verbatim + +This selects the caps font by setting the @code{font-shape} property to +@code{#'caps} for interpreting @code{Text-in-caps}. + +To make the above available as @code{\smallcaps} command, we have to +define a function using @code{def-markup-command}. The command should +take a single argument, of markup type. Therefore, the start of the +definition should read +@example + (def-markup-command (smallcaps paper props argument) (markup?) +@end example + +@noindent + +What follows is the content of the command: we should interpret +the @code{argument} as a markup, i.e. + +@example + (interpret-markup paper @dots{} argument) +@end example + +@noindent +This interpretation should add @code{'(font-shape . caps)} to the active +properties, so we substitute the the following for the @dots{} in the +above example: + +@example + (cons (list '(font-shape . caps) ) props) +@end example + +@noindent +The variable @code{props} is a list of alists, and we prepend to it by +consing a list with the extra setting. + +However, suppose that we are using a font that does not have a +small-caps variant. In that case, we have to fake the small caps font, +by setting a string in upcase, with the first letter a little larger. + +The @code{smallcaps} command first splits its string argument into +tokens separated by spaces (@code{(string-split str #\Space)}); for +each token, a markup is built with the first letter made large and +upcased (@code{#:large (string-upcase (substring s 0 1))}), and a +second markup built with the following letters made tiny and upcased +(@code{#:tiny (string-upcase (substring s 1))}). As LilyPond +introduces a space between markups on a line, the second markup is +translated to the left (@code{#:translate (cons -0.6 0) ...}). Then, +the markups built for each token are put in a line +(@code{(make-line-markup ...)}). Finally, the resulting markup is +passed to the @code{interpret-markup} function, with the @code{paper} +and @code{props} arguments. + +@example +#(def-markup-command (smallcaps paper props str) (string?) + "Print the string argument in small caps. Syntax: \\smallcaps #\"string\"" + (interpret-markup paper props + (make-line-markup + (map (lambda (s) + (if (= (string-length s) 0) + s + (markup #:large (string-upcase (substring s 0 1)) + #:translate (cons -0.6 0) + #:tiny (string-upcase (substring s 1))))) + (string-split str #\Space))))) +@end example + +Finally, suppose that we are typesetting a recitative in an opera, and +we would like to define a command that will show character names in a +custom manner. Names should be printed with small caps and translated a +bit to the left and top. We will define a @code{\character} command +that takes into account the needed translation, and uses the newly +defined @code{\smallcaps} command: + +@verbatim +#(def-markup-command (character paper props name) (string?) + "Print the character name in small caps, translated to the left and + top. Syntax: \\character #\"name\"" + (interpret-markup paper props + (markup "" #:translate (cons -4 2) #:smallcaps name))) +@end verbatim + +There is one complication that needs explanation: texts above and below +the staff are moved vertically to be at a certain distance (the +@code{padding} property) from the staff and the notes. To make sure +that this mechanism does not annihilate the vertical effect of our +@code{#:translate}, we add an empty string (@code{""}) before the +translated text. Now the @code{""} will be put above the notes, and the +@code{name} is moved in relation to that empty string. The net effect is +that the text is moved to the upper left. +The final result is as follows: +@verbatim +\score { + \notes { \fatText + c''^\markup \character #"Cleopatra" + e'^\markup \character #"Giulio Cesare" + } +} +@end verbatim + +@lilypond[raggedright] +#(def-markup-command (smallcaps paper props str) (string?) + "Print the string argument in small caps. Syntax: \\smallcaps #\"string\"" + (interpret-markup paper props + (make-line-markup + (map (lambda (s) + (if (= (string-length s) 0) + s + (markup #:large (string-upcase (substring s 0 1)) + #:translate (cons -0.6 0) + #:tiny (string-upcase (substring s 1))))) + (string-split str #\Space))))) + +#(def-markup-command (character paper props name) (string?) + "Print the character name in small caps, translated to the left and + top. Syntax: \\character #\"name\"" + (interpret-markup paper props + (markup "" #:translate (cons -4 0) #:smallcaps name))) + +\score { + \notes { \fatText + c''^\markup \character #"Cleopatra" + e'^\markup \character #"Giulio Cesare" + } +} +@end lilypond diff --git a/VERSION b/VERSION index 8241cb053e..35298bbb47 100644 --- a/VERSION +++ b/VERSION @@ -1,6 +1,6 @@ PACKAGE_NAME=LilyPond MAJOR_VERSION=2 MINOR_VERSION=1 -PATCH_LEVEL=19 -MY_PATCH_LEVEL=hwn1 +PATCH_LEVEL=20 +MY_PATCH_LEVEL= diff --git a/input/regression/lyric-hyphen-break.ly b/input/regression/lyric-hyphen-break.ly new file mode 100644 index 0000000000..98de34330f --- /dev/null +++ b/input/regression/lyric-hyphen-break.ly @@ -0,0 +1,35 @@ + + +\header { + + texidoc = "Hyphens only print at the beginning of the line, when +they go past the first note. " + + } + +\score { +<< \notes \new Staff \relative c'' { \time 1/4 c16[ c c c] +\time 1/4 +c16[ c c c] +\time 1/4 +r c16[ c c] + +} + \lyrics \new LyricsVoice { + bla16 -- bla -- bla -- bla -- + bla -- bla -- bla -- bla8 -- + bla16 -- bla -- bla + }>> + \paper { + indent = 0.0 \cm + linewidth = 3.4 \cm + + \translator { + \StaffContext \remove "Time_signature_engraver" + } + + } + +} + + diff --git a/input/test/lyric-hyphen-retain.ly b/input/test/lyric-hyphen-retain.ly new file mode 100644 index 0000000000..28a42df033 --- /dev/null +++ b/input/test/lyric-hyphen-retain.ly @@ -0,0 +1,49 @@ + + +\header { + +texidoc = "In tight situations, hyphens are removed, except at the +end of the line. Normally, lyrics aren't set this tight, but by +tuning down @code{padding} of in @code{SeparationItem}, syllables are put closer together, and hyphens may disappear. + +In some languages (eg. German and Hungarian). hyphens should not +disappear, since spelling depends on hyphenation. In this case, +hyphens can be forced to remain by setting @code{minimum-length} on +the LyricHyphen grob. +" + +} + +\score { +<< \notes \new Staff \relative c'' { \time 1/4 c16[ c c c] +\time 1/4 +c16[ c c c] +\time 1/4 +c16[ c c c] + +} + \lyrics \new LyricsVoice \with { + % Otherwise lyrics are so far apart that hyphens don't disappear + SeparationItem \set #'padding = #0.0 + }{ bla -- bla -- bla -- bla -- + bla -- bla -- bla -- bla -- + + \property LyricsVoice . LyricHyphen \set #'minimum-length = #0.7 + \property LyricsVoice . LyricHyphen \set #'spacing-procedure = + #Hyphen_spanner::set_spacing_rods + + bla -- bla -- bla -- bla + }>> + \paper { + indent = 0.0 \cm + linewidth = 3.4 \cm + + \translator { + \StaffContext \remove "Time_signature_engraver" + } + + } + +} + + diff --git a/lily/coherent-ligature-engraver.cc b/lily/coherent-ligature-engraver.cc index 19bc0a15a3..a7e8247d67 100644 --- a/lily/coherent-ligature-engraver.cc +++ b/lily/coherent-ligature-engraver.cc @@ -79,7 +79,7 @@ */ #if 0 // experimental code to collapse spacing after ligature SCM incr_scm = lc->get_grob_property ("forced-spacing"); - if (incr_scm != SCM_EOL) /* (Paper_column::musical_b (l)) */ + if (incr_scm != SCM_EOL) /* (Paper_column::is_musical (l)) */ { me->warning (_f ("gotcha: ptr=%ul", lc));//debug ly_display_scm (lc->self_scm ()); diff --git a/lily/hyphen-engraver.cc b/lily/hyphen-engraver.cc index 1010dc08ab..15f472cadc 100644 --- a/lily/hyphen-engraver.cc +++ b/lily/hyphen-engraver.cc @@ -9,9 +9,9 @@ */ #include "warn.hh" -#include "hyphen-spanner.hh" #include "item.hh" #include "engraver.hh" +#include "spanner.hh" class Hyphen_engraver : public Engraver { diff --git a/lily/hyphen-spanner.cc b/lily/hyphen-spanner.cc deleted file mode 100644 index 09699d7546..0000000000 --- a/lily/hyphen-spanner.cc +++ /dev/null @@ -1,90 +0,0 @@ -/* - hyphen-spanner.cc -- implement Hyphen_spanner - - source file of the GNU LilyPond music typesetter - - (c) 1999--2004 Glen Prideaux - - (adapted from lyric-extender) -*/ - -#include - -#include "box.hh" -#include "lookup.hh" -#include "molecule.hh" -#include "paper-def.hh" -#include "hyphen-spanner.hh" -#include "paper-column.hh" -#include "spanner.hh" -#include "item.hh" - - -MAKE_SCHEME_CALLBACK (Hyphen_spanner,brew_molecule,1) -SCM -Hyphen_spanner::brew_molecule (SCM smob) -{ - Spanner * sp = unsmob_spanner (smob); - Drul_array bounds (sp->get_bound (LEFT), - sp->get_bound (RIGHT)); - - Grob * common = bounds[LEFT]->common_refpoint (bounds[RIGHT], X_AXIS); - - Interval span_points; - Direction d = LEFT; - do - { - Interval iv = bounds[d]->extent (common, X_AXIS); - - span_points[d] = iv.is_empty () - ? bounds[d]->relative_coordinate (common, X_AXIS) - : iv[-d]; - } - while (flip (&d) != LEFT); - - Real lt = sp->get_paper ()->get_realvar (ly_symbol2scm ("linethickness")); - Real th = robust_scm2double (sp->get_grob_property ("thickness"), 1) * lt ; - Real h = robust_scm2double (sp->get_grob_property ("height"), 0.5); - - // interval? - - Real dp = robust_scm2double (sp->get_grob_property ("dash-period"), 1.0); - Real dl = robust_scm2double (sp->get_grob_property ("length"), .5 ); - - if (dp < dl) - dp = 1.5 * dl; - - Real l = span_points.length (); - int n = int (ceil (l/dp - 0.5)); - if (n <= 0) - n = 1; - - Real space_left = l - dl - (n-1)* dp; - - /* - If there is not enough space, the hyphen should disappear. - */ - if (space_left < 0) - return SCM_EOL; - - Box b (Interval (0, dl), Interval (h,h+th)); - Molecule dash_mol (Lookup::round_filled_box (b, 0.8 * lt)); - - Molecule total; - for (int i = 0; i < n; i++) - { - Molecule m (dash_mol); - m.translate_axis (span_points[LEFT] + i * dp + space_left / 2, X_AXIS); - total.add_molecule (m); - } - - total.translate_axis ( -sp->relative_coordinate (common, X_AXIS), X_AXIS); - return total.smobbed_copy (); -} - - -ADD_INTERFACE (Hyphen_spanner, "lyric-hyphen-interface", - "A centred hyphen is a simple line between lyrics used to divide syllables", - "thickness height dash-period length"); - - diff --git a/lily/include/hyphen-spanner.hh b/lily/include/lyric-hyphen.hh similarity index 90% rename from lily/include/hyphen-spanner.hh rename to lily/include/lyric-hyphen.hh index cd713c4a35..ce04811c91 100644 --- a/lily/include/hyphen-spanner.hh +++ b/lily/include/lyric-hyphen.hh @@ -13,7 +13,6 @@ struct Hyphen_spanner { public: DECLARE_SCHEME_CALLBACK(set_spacing_rods, (SCM)); - void set_textitem (Direction, Grob*); bool has_interface (Grob*); DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM )); }; diff --git a/lily/include/paper-column.hh b/lily/include/paper-column.hh index f44ea9ac15..43be74ba7e 100644 --- a/lily/include/paper-column.hh +++ b/lily/include/paper-column.hh @@ -7,8 +7,8 @@ */ -#ifndef P_COL_HH -#define P_COL_HH +#ifndef PAPER_COLUMN_HH +#define PAPER_COLUMN_HH #include "item.hh" #include "rod.hh" @@ -34,12 +34,12 @@ public: DECLARE_SCHEME_CALLBACK(before_line_breaking, (SCM)); Paper_column (SCM); - static bool musical_b (Grob *); + static bool is_musical (Grob *); static Moment when_mom (Grob*); - static bool used_b (Grob*) ; + static bool is_used (Grob*) ; void set_rank (int); }; -#endif // P_COL_HH +#endif // PAPER_COLUMN_HH diff --git a/lily/lyric-hyphen.cc b/lily/lyric-hyphen.cc new file mode 100644 index 0000000000..6fdd1e4b62 --- /dev/null +++ b/lily/lyric-hyphen.cc @@ -0,0 +1,116 @@ +/* + hyphen-spanner.cc -- implement Hyphen_spanner + + source file of the GNU LilyPond music typesetter + + (c) 2003--2004 Han-Wen Nienhuys +*/ + +#include + +#include "box.hh" +#include "lookup.hh" +#include "molecule.hh" +#include "paper-def.hh" +#include "paper-column.hh" +#include "spanner.hh" +#include "item.hh" +#include "lyric-hyphen.hh" +#include "moment.hh" + +MAKE_SCHEME_CALLBACK (Hyphen_spanner,brew_molecule,1) +SCM +Hyphen_spanner::brew_molecule (SCM smob) +{ + Spanner * me = unsmob_spanner (smob); + Drul_array bounds (me->get_bound (LEFT), + me->get_bound (RIGHT)); + + if (bounds[LEFT]->break_status_dir () + && Paper_column::when_mom (bounds[LEFT]) == Paper_column::when_mom (bounds[RIGHT]->get_column())) + return SCM_EOL; + + Grob * common = bounds[LEFT]->common_refpoint (bounds[RIGHT], X_AXIS); + + Interval span_points; + Direction d = LEFT; + do + { + Interval iv = bounds[d]->extent (common, X_AXIS); + + span_points[d] = iv.is_empty () + ? bounds[d]->relative_coordinate (common, X_AXIS) + : iv[-d]; + } + while (flip (&d) != LEFT); + + Real lt = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness")); + Real th = robust_scm2double (me->get_grob_property ("thickness"), 1) * lt ; + Real h = robust_scm2double (me->get_grob_property ("height"), 0.5); + + // interval? + + Real dp = robust_scm2double (me->get_grob_property ("dash-period"), 1.0); + Real dl = robust_scm2double (me->get_grob_property ("length"), .5 ); + + if (dp < dl) + dp = 1.5 * dl; + + Real l = span_points.length (); + int n = int (ceil (l/dp - 0.5)); + if (n <= 0) + n = 1; + + Real space_left = l - dl - (n-1)* dp; + + /* + If there is not enough space, the hyphen should disappear, but not + at the end of the line. + */ + if (space_left < 0.0 + && !bounds[RIGHT]->break_status_dir ()) + return SCM_EOL; + + space_left = space_left >? 0.0; + + Box b (Interval (0, dl), Interval (h,h+th)); + Molecule dash_mol (Lookup::round_filled_box (b, 0.8 * lt)); + + Molecule total; + for (int i = 0; i < n; i++) + { + Molecule m (dash_mol); + m.translate_axis (span_points[LEFT] + i * dp + space_left / 2, X_AXIS); + total.add_molecule (m); + } + + total.translate_axis ( -me->relative_coordinate (common, X_AXIS), X_AXIS); + return total.smobbed_copy (); +} + + +MAKE_SCHEME_CALLBACK (Hyphen_spanner,set_spacing_rods,1); +SCM +Hyphen_spanner::set_spacing_rods (SCM smob) +{ + Grob*me = unsmob_grob (smob); + + Rod r; + Spanner*sp = dynamic_cast (me); + r.distance_ = + robust_scm2double (me->get_grob_property ("minimum-length"), 0); + Direction d=LEFT; + do { + r.item_l_drul_[d] = sp->get_bound (d); + r.distance_ += r.item_l_drul_[d]->extent (r.item_l_drul_[d], X_AXIS)[-d]; + } while (flip (&d) != LEFT); + + r.add_to_cols (); + return SCM_UNSPECIFIED; +} + +ADD_INTERFACE (Hyphen_spanner, "lyric-hyphen-interface", + "A centred hyphen is a simple line between lyrics used to divide syllables", + "thickness height dash-period minimum-length length"); + + diff --git a/lily/new-part-combine-iterator.cc b/lily/new-part-combine-iterator.cc index ee4ede13ad..ceae7e03b5 100644 --- a/lily/new-part-combine-iterator.cc +++ b/lily/new-part-combine-iterator.cc @@ -312,6 +312,7 @@ New_pc_iterator::construct_children () "DynamicLineSpanner", "Tie", "Dots", + "Rest", "Slur", "TextScript", "Script", diff --git a/lily/paper-column.cc b/lily/paper-column.cc index 60fd60a59f..eab40b4975 100644 --- a/lily/paper-column.cc +++ b/lily/paper-column.cc @@ -86,7 +86,7 @@ Paper_column::when_mom (Grob*me) } bool -Paper_column::musical_b (Grob *me) +Paper_column::is_musical (Grob *me) { SCM m = me->get_grob_property ("shortest-starter-duration"); Moment s (0); @@ -100,7 +100,7 @@ Paper_column::musical_b (Grob *me) bool -Paper_column::used_b (Grob*me) +Paper_column::is_used (Grob*me) { return gh_pair_p (me->get_grob_property ("elements")) || Item::breakable_b (me) || gh_pair_p (me->get_grob_property ("bounded-by-me")) diff --git a/lily/system.cc b/lily/system.cc index dc7bba5b15..3a0f2dbaa3 100644 --- a/lily/system.cc +++ b/lily/system.cc @@ -602,7 +602,7 @@ System::columns ()const seem empty. We need to retain breakable columns, in case someone forced a breakpoint. */ - if (!bfound || !Paper_column::used_b (acs[i])) + if (!bfound || !Paper_column::is_used (acs[i])) acs.del (i); } return acs; diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly index 5663553a91..aecfe99c24 100644 --- a/ly/engraver-init.ly +++ b/ly/engraver-init.ly @@ -343,7 +343,7 @@ printing of a single line of lyrics. " \consists "Stanza_number_engraver" \consists "Vocal_name_engraver" \consists "Skip_event_swallow_translator" - SeparationItem \set #'padding = #0.5 + SeparationItem \set #'padding = #0.2 } \translator { diff --git a/make/ly-rules.make b/make/ly-rules.make index d513ae3dcf..174dee86eb 100644 --- a/make/ly-rules.make +++ b/make/ly-rules.make @@ -10,7 +10,7 @@ $(outdir)/%.latex: %.doc # it is not, for --srcdir builds $(outdir)/%.texi: %.tely if [ -f $@ ]; then chmod a+w $@; fi - time $(PYTHON) $(LILYPOND_BOOK) $(LILYPOND_BOOK_INCLUDES) --process='$(LILYPOND) $(LILYPOND_BOOK_INCLUDES)' --output=$(outdir) --format=$(LILYPOND_BOOK_FORMAT) --verbose $(LILYPOND_BOOK_FLAGS) $< + $(PYTHON) $(LILYPOND_BOOK) $(LILYPOND_BOOK_INCLUDES) --process='$(LILYPOND) $(LILYPOND_BOOK_INCLUDES)' --output=$(outdir) --format=$(LILYPOND_BOOK_FORMAT) --verbose $(LILYPOND_BOOK_FLAGS) $< chmod -w $@ $(outdir)/%.texi: $(outdir)/%.tely diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm index 95d8bb545d..89dc980d67 100644 --- a/scm/define-grobs.scm +++ b/scm/define-grobs.scm @@ -491,7 +491,7 @@ (height . 0.42) (dash-period . 10.0) (length . 0.66) - (minimum-length . 0.5) + (spacing-procedure . ,Hyphen_spanner::set_spacing_rods) (molecule-callback . ,Hyphen_spanner::brew_molecule) (Y-extent-callback . ,Grob::point_dimension_callback) (meta . ((interfaces . (lyric-interface lyric-hyphen-interface diff --git a/scripts/lilypond-book.py b/scripts/lilypond-book.py index 85c39d2ad3..fe1157ccbd 100644 --- a/scripts/lilypond-book.py +++ b/scripts/lilypond-book.py @@ -156,9 +156,11 @@ snippet_res = { 'lilypond_block': r'''(?ms)^(?P@lilypond(\[(?P[^]]*)\])?\s(?P.*?)@end lilypond)\s''', 'lilypond_file': '(?m)^(?P@lilypondfile(\[(?P[^]]*)\])?{(?P[^}]+)})', 'multiline_comment': r"(?sm)^\s*(?!@c\s+)(?P@ignore\s.*?@end ignore)\s", - 'singleline_comment': r"(?m)^.*?(?P(?P@c([ \t][^\n]*|)\n))", - 'verb': r'''(?P@code{.*?})''', - 'verbatim': r'''(?s)(?P@example\s.*?@end example\s)''', + 'singleline_comment': r"(?m)^.*(?P(?P@c([ \t][^\n]*|)\n))", + +# don't do this: fucks up with @code{@{} +# 'verb': r'''(?P@code{.*?})''', + 'verbatim': r'''(?s)(?P@example\s.*?@end\s+example\s)''', }, } @@ -377,7 +379,8 @@ def split_options (option_string): class Chunk: def replacement_text (self): return '' - + def is_outdated (self): + return 0 class Substring (Chunk): def __init__ (self, source, start, end): @@ -386,8 +389,6 @@ class Substring (Chunk): self.end = end def replacement_text (self): return self.source [self.start:self.end] - def outdated_p (self): - return 0 class Snippet (Chunk): def __init__ (self, type, match, format): @@ -396,6 +397,9 @@ class Snippet (Chunk): self.hash = 0 self.options = [] self.format = format + def replacement_text (self): + return self.match.group (0) + def substring (self, s): return self.match.group (s) def filter_code (self): @@ -404,12 +408,15 @@ class Snippet (Chunk): return `self.__class__` + " type = " + self.type class Include_snippet (Snippet): + def processed_filename (self): + f = self.substring ('filename') + return os.path.splitext (f)[0] + format2ext[format] + def replacement_text (self): s = self.match.group (0) f = self.substring ('filename') - nf = os.path.splitext (f)[0] + format2ext[format] - - return re.sub (f, nf, s) + + return re.sub (f, self.processed_filename (), s) class Lilypond_snippet (Snippet): def __init__ (self, type, match, format): @@ -446,7 +453,7 @@ class Lilypond_snippet (Snippet): outf = open (self.basename () + '.ly', 'w') outf.write (self.full_ly ()) - def outdated_p (self): + def is_outdated (self): base = self.basename () if os.path.exists (base + '.ly') \ and os.path.exists (base + '.tex') \ @@ -691,6 +698,7 @@ format2ext = { LATEX: '.tex', } + def do_file (input_filename): #ugh global format @@ -714,7 +722,7 @@ def do_file (input_filename): ly.progress (_ ("Dissecting...")) snippet_types = ( 'lilypond_block', - 'verb', +# 'verb', 'verbatim', 'singleline_comment', 'multiline_comment', @@ -760,7 +768,7 @@ def do_file (input_filename): if filter_cmd: pass # todo elif process_cmd: - outdated = filter (lambda x: x.__class__ == Lilypond_snippet and x.outdated_p (), + outdated = filter (lambda x: x.__class__ == Lilypond_snippet and x.is_outdated (), chunks) ly.progress (_ ("Writing snippets...")) map (Lilypond_snippet.write_ly, outdated) @@ -787,9 +795,24 @@ def do_file (input_filename): output_file.writelines ([s.replacement_text () for s in chunks]) - ## UGH. how do you do dynamic_cast/typecheck in Python? + + included_files = [] + def notice_include (target, snip): + included_files.append (snip.match.group ('filename')) + included_files.append (os.path.join (output_name, snip.processed_filename ())) + + [notice_include (output_filename, x) for x in + + ## UGH. how do you do dynamic_cast/typecheck in Python? + filter (lambda x: x.__class__ == Include_snippet, chunks)] + + target = re.sub (r'^\./','', output_filename) + open (os.path.split (output_filename)[1] + '.dep', 'w').write ('%s: %s\n' % (target, + string.join (included_files))) + map (process_include, filter (lambda x: x.__class__ == Include_snippet, chunks)) + def do_options (): global format, output_name global filter_cmd, process_cmd, verbose_p @@ -853,6 +876,5 @@ def main (): ly.setup_environment () if files: do_file (files[0]) - if __name__ == '__main__': main () -- 2.39.5