From 5539198caa04c4825782da9f603216fa0f9568b8 Mon Sep 17 00:00:00 2001 From: fred Date: Wed, 27 Mar 2002 00:35:00 +0000 Subject: [PATCH] lilypond-1.3.119 --- Documentation/user/development.itexi | 866 +++++++++++++++++++++++++++ Documentation/user/lilypond.tely | 4 + Documentation/user/refman.itely | 366 +---------- lily/include/engraver.hh | 5 +- 4 files changed, 900 insertions(+), 341 deletions(-) create mode 100644 Documentation/user/development.itexi diff --git a/Documentation/user/development.itexi b/Documentation/user/development.itexi new file mode 100644 index 0000000000..e01549b272 --- /dev/null +++ b/Documentation/user/development.itexi @@ -0,0 +1,866 @@ +@node Internals, , , top + +@menu +* Conversion stages:: Lilypond is a multi-pass program. + +* Grobs:: Graphical object +* Engraver:: +* Music_iterator:: +* Music:: +* Molecule:: Molecule are stand-alone descriptions of output +@end menu + + +@node Conversion stages, , , Internals + +When translating the input to notation, there are number of distinct +phases. We list them here: + + +@table @samp + +@item Parsing: + +The .ly file is read, and converted to a list of @code{Scores}, which +each contain @code{Music} and paper/midi-definitions. + +@item Interpreting music + +All music events are "read" in the same order as they would be played +(or read from paper). At every step of the interpretation, musical +events are delivered to +interpretation contexts, +@cindex engraver +which use them to build grobs (or MIDI objects, for MIDI output). + +@item Prebreaking + +At places where line breaks may occur, clefs and bars are prepared for +a possible line break. + +@item Preprocessing + +In this stage, all information that is needed to determine line breaking +is computed. + +@item Break calculation: + +The lines and horizontal positions of the columns are determined. + +@item Breaking + +Relations between all grobs are modified to reflect line breaks. See +also @ref{Pointer substitution}. + +@item Outputting: + +All vertical dimensions and spanning objects are computed, and all grobs +are output, line by line. + +@end table + + +@node Grobs, , , Internals +@section Grobs + +This section is about Grobs (short for Graphical Objects), which are +formatting objects used to create the final output. This material is +normally the domain of LilyPond gurus, but occasionally, a normal user +also has to deal with grobs. + +The most simple interaction with Grobs are when you use +@code{\override}: + +@example + \property Voice.Stem \override #'direction = #1 +@end example + +This piece of lily input causes all stem objects to be stem-up +henceforth. In effect, you are telling lilypond to extend the defintion +of the "Stem" grob with the setting @code{direction := 1}. Of course +there are many more ways of customizing Lily output, and since most of +them involve Grobs in some form, this section explains some details of +how grobs work. + +@menu +* What is a grob?:: +* Callbacks:: +* Setting grob properties:: +* Items and Spanners:: +* Pointer substitution:: +@end menu + +@node What is a grob?, , , Grobs + +In music notation, lots of symbols are related in some way. You can +think of music notation as a graph where nodes are formed by the +symbols, and the arcs by their relations. A grob is node in that +graph. A grob stores references to other grobs, the directed edges in +the graph. + +The objective of this big graph of grobs, is to specify the notation +problem. The solution of this problem is a description of the printout +that is in closed form, i.e. but a list of values. These values are +Molecules. (see @ref{Molecules}) + +All grobs have an X and Y-position on the page. These X and Y positions +are stored in a relative format, so they can easily be combined by +stacking them, hanging one grob to the side of another, and coupling +them into a grouping-grob. + +Each grob has a reference point, or parent: the position of a grob is +stored relative to that reference point. For example the X-reference +point of a staccato dot usually is the note head that it applies +to. Whenever the note head is moved, the staccato dot moves along +automatically. + +If you keep following offset reference points, you will always end up at +the root-object. This root object is called @code{Line_of_score} +@ref{(lilypond-internals)Element Line_of_score}, and it represents a +system (ie. a line of music). + +All grobs carry a set of grob-properties. In the Stem example above, +the property @code{direction} is set to value @code{1}. The function +that draws the symbol (@code{Stem::brew_molecule}) uses the value of +@code{direction} to determine how to print the stem and the flag. The +appearance of a grob is determined solely by the values of its +properties. + +Often, a grob also is associated with a symbol. On the other hand, +Some grobs do not print any symbols, but take care of grouping +objects. For example, there is a separate grob that stacks staffs +vertically, so they are not printed in overstrike. The NoteCollision +@ref{(lilypond-internals)Element NoteCollision} is another example of +an abstract grob. It only moves around chords, but doesn't print +anything. + +A complete list of grob types is found in +@ref{(lilypond-internals)Elements} + +Grobs are created in the "Interpreting music" phase, by things in +LilyPond called engravers. In this phase of the translation, a load of +grobs are created, and they are linked into a giant network of objects. +This network of grobs forms the "specification" of the print +problem. This problem is then solved: configurations, directions, +dimensions, line breaks, etc. are calculated. Finally, the printing +description in the form of Molecules (@ref{Molecule}) is extracted from +the network. These are then dumped into the output file + +@node Callbacks, , , Grobs + +Offsets of grobs are relative to a parent reference point. Most +positions are not known when an object is created, so these are +calculated as needed. This is done by adding a callback for a specific +direction. + +Suppose you have the following code in a .ly file. +@example + #(define (my-callback gr axis) + (* 2.0 (get-gr-property grob 'direction)) + ) + +.... + + \property Voice.Stem \override #'Y-offset-callbacks = #(list + my-callback) +@end example + +When the Y-offset of a Stem object is needed, LilyPond will +automatically execute all callbacks for that object. In this case, it +will find @code{my-callback}, and execute that. The result is that the +stem is translated by two staff spaces in its direction. + +(note: Y-offset-callbacks is also a property) + + +Offset callbacks can be stacked, ie. + +@example + \property .... \override #'Y-offset-callbacks = #(list + callback1 callback2 callback3) + +@end example + +The callbacks will be executed in the order callback3 callback2 +callback1. This is used for quantized positioning: the staccato dot is +above or below a note head, and it must not be on a staff-line. + +To achieve this, for the staccato there are two callbacks: one callback +that positions the grob above or below the note head, and one callback +that rounds the Y-position of the grob to the nearest open space. + +Similarly, the size of a grob are determined through callbacks, settable +with grob properties @code{X-extent-callback} and @code{Y-extent-callback}. +There can be only one extent-callback for each axis. No callback (value #f) +means: "empty in this direction". If you fill in a pair, that pair +hard-codes the extent in that coordinate. + + +@node Setting grob properties, , , Grobs + +Grob properties are stored as GUILE association lists, with symbols as +keys. From C++, element properties can be accessed using the functions + +@example + SCM get_grob_property (SCM) const; + void set_grob_property (const char * , SCM val); + void set_immutable_grob_property (const char * , SCM val); + void set_immutable_grob_property (SCM key, SCM val); + void set_grob_property (SCM , SCM val); + void set_grob_pointer (const char*, SCM val); + SCM remove_grob_property (const char* nm); +@end example + +In GUILE, LilyPond provides + +@example + ly-get-grob-property GROB SYMBOL + ly-set-grob-property GROB SYMBOL VALUE +@end example + +All lookup functions identify undefined properties with +end-of-list (ie. @code{'()} in Scheme or @code{SCM_EOL} in C) + +Properties are stored in two ways: +@itemize @bullet +@item mutable properties: +element properties that change from object to object. The storage of +these are private to a grob. Typically this is used to store lists of +pointers to other grobs + +@item immutable properties: +element properties that are shared across different grobs of the same +type. The storage is shared, and hence it is read-only. Typically, this +is used to store function callbacks, and values for shared element +properties are read from @file{scm/element-description.scm}. +@end itemize + +There are two ways to manually set grob properties. + +You can change immutable grob properties. This is done with the +\override syntax: + +@example + \property Voice.Stem \override #'direction = #1 +@end example + +This will push the entry @code{'(direction . 1)} on the immutable +property list for stems, in effect overriding the setting from +@file{scm/element-description.scm}. This can be undone by + +@example + \property Voice.stem \revert #'direction +@end example + +If you use this a lot, this gets old quickly. So we also have a +shorthand, + +@example + \property Context.GrobType \set #'prop = #VAL +@end example + +this does a @code{\revert} followed by a @code{\override} + +The second way is \outputproperty. This construct looks like + +@example + \context ContextName \outputproperty @var{pred} #@var{sym} = #@var{val} +@end example + +In this case, in every grob that satisfies @var{pred}, the property +assignment @var{sym} = @var{val} is done. For example + +@example + \outputproperty + #(lambda (gr) (string? (ly-get-grob-property gr + 'text))) + #'extra-offset = #'(-1.0 . 0.0) +@end example + +This shifts all elements that have a @code{text} property one staff +space to the left. This mechanism is rather clumsy to use, but it allows +you tweak any setting of any grob. + +@node Items and Spanners, , , Grobs +@unnumberedsubsec Items and Spanners + +Grobs can also be distinguished in their role in the horizontal spacing. +A lot of grobs define constraints on the spacing by their sizes. For +example, note heads, clefs, stems, and all other symbols with a fixed +shape. These grobs form a subtype called @code{Item}. + +Other grobs have a shape that depends on the horizontal spacing. For +example, slur, beam, tie, etc. These grobs form a subtype called +@code{Spanner}. All spanners have two span-points (these must be +@code{Item}s), one on the left and one on the right. The left bound is +also the X-reference point. + +Some items need special treatment for line breaking. For example, a +clef is normally only printed at the start of a line (ie. after a line +break). To model this, `breakable' items (clef, key signature, bar lines, +etc.) are copied twice. Then we have three versions of each breakable +item: one version if there is no line break, one version that is printed +before the line break (at the end of a system), one version that is +printed after the line break. + +Whether these versions are visible and take up space, is determined by +the outcome of the visibility-lambda. This is a function taking a +direction (-1, 0 or 1) and returns a cons of booleans, signifying wether +this grob should be transparent and invisible. + +@node Pointer substitution, , , Grobs +@unnumberedsubsec Pointer substitution + + +Symbols that cross line-breaks (such as slurs) cause some more +complications. When a spanner crosses a line-break, then the spanner is +"broken into pieces", for every line that the spanner is in, a copy of +the grob is made. A substitution process redirects all grob-reference +so that spanner grob will only reference other grobs in the same line. + +@node Engraver, , , Internals + +@node Music_iterator, , , Internals + +@node Music, , , Internals + +@node Molecule, , , Internals + +The objective of any typesetting system is to put ink on paper in the +right places. For LilyPond, this final stage is left to the TeX and the +printer subsystem. For lily, the last stage in processing a score is +outputting a description of what to put where. This description roughly +looks like + +@example + PUT glyph AT (x,y) + PUT glyph AT (x,y) + PUT glyph AT (x,y) +@end example + +you merely have to look at the tex output of lily to see this. +Internally these instructions are encoded in Molecules:@footnote{At some +point LilyPond also contained Atom-objects, but they have been replaced +by Scheme expressions.}. A molecule is an object that combines +dimension information (how large is this glyph ?) with +what-to-print-where. + +Conceptually, Molecules can be constructed from Scheme code, by +translating a Molecule and by combining two molecules. In BNF notation: + +@example + Molecule = COMBINE Molecule Molecule + | TRANSLATE Offset Molecule + | GLYPH-DESCRIPTION + ; +@end example + +(refer to the C++ code for more details). All visible, +ie. non-transparent, grobs have a callback to create a Molecule. The +name of the property is @code{molecule-callback}, and its value should +be a Scheme function taking one argument (the grob) and returning a +Molecule. + + + +@node Development, , , top +@chapter Development + +@menu +* Coding standards:: +* Making patches:: +* Localisation:: +@end menu + +@section CodingStyle - standards while programming for GNU LilyPond + +As a general rule, you should always try to continue computations, even +if there is some kind of error. When the program stops, it is often very +hard for a user to pinpoint what part of the input causes an +error. Finding the culprit is much easier if there is some viewable +output. + +So functions and methods do not return errorcodes, they never crash, but +report a programming_error and try to carry on. + +@unnumberedsubsec Languages + +C++ and Python are preferred. Python code should use an indent of 8, +using TAB characters. + +@unnumberedsubsec Filenames + +Definitions of classes that are only accessed via pointers +(*) or references (&) shall not be included as include files. + +filenames + +@example + ".hh" Include files + ".cc" Implementation files + ".icc" Inline definition files + ".tcc" non inline Template defs +@end example + +in emacs: + +@example + (setq auto-mode-alist + (append '(("\\.make$" . makefile-mode) + ("\\.cc$" . c++-mode) + ("\\.icc$" . c++-mode) + ("\\.tcc$" . c++-mode) + ("\\.hh$" . c++-mode) + ("\\.pod$" . text-mode) + ) + auto-mode-alist)) +@end example + + +The class Class_name is coded in @file{class-name.*} + +@unnumberedsubsec Indentation + +Standard GNU coding style is used. In emacs: + +@example + (add-hook 'c++-mode-hook + '(lambda() (c-set-style "gnu") + ) + ) +@end example + +If you like using font-lock, you can also add this to your @file{.emacs}: + +@example + (setq font-lock-maximum-decoration t) + (setq c++-font-lock-keywords-3 + (append + c++-font-lock-keywords-3 + '(("\\b\\([a-zA-Z_]+_\\)\\b" 1 font-lock-variable-name-face) + ("\\b\\([A-Z]+[a-z_]+\\)\\b" 1 font-lock-type-face)) + )) +@end example + +@unnumberedsubsec Classes and Types + +@example + This_is_a_class +@end example + +@unnumberedsubsec Members + +@example + Class::member () + Type Class::member_type_ + Type Class::member_type () +@end example + +the @code{type} is a Hungarian notation postfix for @code{Type}. See below + +@unnumberedsubsec Macros + +Macro names should be written in uppercase completely. + +@unnumberedsubsec Broken code + +Try not to write broken code. This includes hardwired dependencies, +hardwired constants, slow algorithms and obvious limitations. If you can +not avoid it, mark the place clearly, and add a comment explaining +shortcomings of the code. + +@unnumberedsec Hungarian notation naming convention + +The C++ part of LilyPond uses a naming convention derived from the +so-called @emph{Hungarian Notation}. Macros, @code{enum}s and +@code{const}s are all uppercase, with the parts of the names separated +by underscores. + +The hungarian notation is to be used when variables are not declared +near usage (mostly in member variables and functions). + +@unnumberedsubsec Types + +@table @samp +@item @code{byte} + unsigned char. (The postfix _by is ambiguous) +@item @code{b} + bool +@item @code{bi} + bit +@item @code{ch} + char +@item @code{f} + float +@item @code{i} + signed integer +@item @code{str} + string class +@item @code{sz} + Zero terminated c string +@item @code{u} + unsigned integer +@end table + +@unnumberedsubsec User defined types + +@example + + /* + Slur blah. blah. + */ + class Slur @{ + ... + @}; + Slur* slur_p = new Slur; + +@end example + +@unnumberedsubsec Modifiers + +The following types modify the meaning of the prefix. +These are preceded by the prefixes: + +@table @samp +@item @code{a} + array +@item @code{arr} + user built array. +@item @code{c} + const. Note that the proper order is @code{Type const} + and not @code{const Type} +@item @code{C} + A const pointer. This would be equivalent to @code{_c_l}, but since any + "const" pointer has to be a link (you can't delete a const pointer), + it is superfluous. +@item @code{l} + temporary pointer to object (link) +@item @code{p} + pointer to newed object +@item @code{r} + reference +@end table + +@unnumberedsubsec Adjective + +Adjectives such as global and static should be spelled out in full. +They come before the noun that they refer to, just as in normal english. + +@example + +foo_global_i: a global variable of type int commonly called "foo". + +@end example + +static class members do not need the static_ prefix in the name (the +Class::var notation usually makes it clear that it is static) + +@table @samp +@item @code{loop_i} + Variable loop: an integer +@item @code{u} + Temporary variable: an unsigned integer +@item @code{test_ch} + Variable test: a character +@item @code{first_name_str} + Variable first_name: a String class object +@item @code{last_name_ch_a} + Variable last_name: a @code{char} array +@item @code{foo_i_p} + Variable foo: an @code{Int*} that you must delete +@item @code{bar_i_l} + Variable bar: an @code{Int*} that you must not delete +@end table + +Generally default arguments are taboo, except for nil pointers. + +The naming convention can be quite conveniently memorised, by +expressing the type in english, and abbreviating it + +@example + + static Array foo + +@end example + +@code{foo} can be described as "the static int-pointer user-array", so you get + +@example + + foo_static_l_arr + +@end example + + +@unnumberedsec Miscellaneous + +For some tasks, some scripts are supplied, notably creating patches, a +mirror of the website, generating the header to put over cc and hh +files, doing a release. + +Use them. + +@node Making patches, , , Top + + +@unnumberedsec Track and distribute your code changes + +This page documents how to distribute your changes to GNU lilypond + +We would like to have unified context diffs with full pathnames. A +script automating supplied with Lily. + +Distributing a change normally goes like this: + +@itemize @bullet +@item make your fix/add your code +@item Add changes to CHANGES, and add yourself to Documentation/topdocs/AUTHORS.texi +@item generate a patch, +@item e-mail your patch to one of the mailing lists + gnu-music-discuss@@gnu.org or bug-gnu-music@@gnu.org +@end itemize + +Please do not send entire files, even if the patch is bigger than the +original. A patch makes it clear what is changed, and it won't +overwrite previous (not yet released) changes. + +@unnumberedsec Generating a patch + +Simple version: run + +@example + make -C lilypond-x.y.z/ distclean + make -C lilypond-x.y.z.NEW/ distclean + diff -urN lilypond-x.y.z/ lilypond-x.y.z.NEW/ +@end example + +Complicated (but automated) version: + +In @file{VERSION}, set MY_PATCH_LEVEL: + +@example + + VERSION: + ... + MY_PATCH_LEVEL=jcn1 + +@end example + +In @file{CHANGES}, enter a summary of changes: + +@example + 0.1.73.jcn1 + =========== + + * A concise, yet clearly readable description of what changed. + +@end example + +Then, from the top of Lily's source tree, type + +@example + make release +@end example + +These handy python scripts assume a directory structure which looks +like: + +@example + + lilypond -> lilypond-x.y.z # symlink to development directory + lilypond-x.y.z/ # current development + patches/ # patches between different releases + releases/ # .tar.gz releases + +@end example + +@unnumberedsec Applying patches + +[outdated: please use xdeltas] + +If you're following LilyPond development regularly, you probably want to +download just the patch for each subsequent release. +After downloading the patch (into the patches directory, of course), simply +apply it: + +@example + + gzip -dc ../patches/lilypond-0.1.74.diff.gz | patch -p1 -E + +@end example + +and don't forget to make automatically generated files: + +@example + + autoconf footnote(patches don't include automatically generated files, + i.e. file(configure) and files generated by file(configure).) + + configure + +@end example + +@node Localisation, , , Top + +@chapter Localisation - User messages in LilyPond + +@section Introduction + +This document provides some guidelines for uniformising user messages. +In the absence of other standards, we'll be using these rules when coding + for LilyPond. Hopefully, this can be replaced by general GNU +guidelines in the future. + +Not-preferred messages are marked with @code{+}. By convention, +agrammatical examples are marked with @code{*}. + +@section Guidelines + +@itemize @bullet + +@item +Every message to the user should be localised (and thus be marked +for localisation). This includes warning and error messages. + +@item +Don't localise/gettextify: + +@itemize @minus +@item @code{programming_error ()}s +@item @code{programming_warning ()}s +@item debug strings +@item output strings (PostScript, TeX) +@end itemize + +@item +Messages to be localised must be encapsulated in @code{_ (STRING)} +or @code{_f (FORMAT, ...)}. Eg: + +@example +warning (_ ("Need music in a score")); +error (_f ("Can't open file: `%s'", file_name)); +@end example + +In some rare cases you may need to call @code{gettext ()} by hand. +This happens when you pre-define (a list of) string constants for later +use. In that case, you'll probably also need to mark these string +constants for translation, using @code{_i (STRING)}. The @code{_i} +macro is a no-op, it only serves as a marker for @file{xgettext}. + +@example +char const* messages[] = @{ + _i ("enable debugging output"), + _i ("ignore lilypond version"), + 0 +@}; + +void +foo (int i) +@{ + puts (gettext (messages [i])); +@} +@end example + +See also +@file{flower/getopt-long.cc} and @file{lily/main.cc}. + +@item +Don't use leading or trailing whitespace in messages. + +@item +Messages containing a final verb, or a gerund (@code{-ing}-form) +always start with a capital. Other (simpler) messages start with +a lowercase letter: + +@example +The word `foo' is not declared. +`foo': not declared. +Not declaring: `foo'. +@end example + +@item +To avoid having a number of different messages for the same situation, +we'll use quoting like this @code{"message: `%s'"} for all strings. +Numbers are not quoted: + +@example +_f ("Can't open file: `%s'", name_str) +_f ("Can't find charater number: %d", i) +@end example + +@item +Think about translation issues. In a lot of cases, it is better to +translate a whole message. The english grammar mustn't be imposed on +the translator. So, iso + +@example +_ ("Stem at ") + moment.str () + _(" doen't fit in beam") +@end example + +@noindent +have + +@example +_f ("Stem at %s doen't fit in beam", moment.str ()) +@end example + +@item +Split up multi-sentence messages, whenever possible. Instead of + +@example +warning (_f ("out of tune! Can't find: `%s', "Key_engraver")); + +warning (_f ("Can't find font `%s', loading default", + font_name)); +@end example + +@noindent +rather say: + +@example +warning (_ ("out of tune:"); +warning (_f ("Can't find: `%s', "Key_engraver")); + +warning (_f ("Can't find font: `%s', font_name)); +warning (_f ("Loading default font")); +@end example + +@item +If you must have multiple-sentence messages, use full punctuation. +Use two spaces after end of sentence punctuation. +No punctuation (esp. period) is used at the end of simple messages. + +@example + _f ("Non-matching braces in text `%s', adding braces", text) + _ ("Debug output disabled. Compiled with NPRINT.") + _f ("Huh? Not a Request: `%s'. Ignoring.", request) +@end example + +@item +Don't modularise too much; a lot of words cannot be translated +without context. +It's probably safe to treat most occurences of words like +stem, beam, crescendo as separately translatable words. + +@item +When translating, it is preferrable to put interesting information +at the end of the message, rather than embedded in the middle. +This especially applies to frequently used messages, even if this +would mean sacrificing a bit of eloquency. This holds for original +messages too, of course. + +@example + en: can't open: `foo.ly' ++ nl: kan `foo.ly' niet openen (1) + kan niet openen: `foo.ly'* (2) + niet te openen: `foo.ly'* (3) +@end example + +The first nl message, although gramatically and stylishly correct, +is not friendly for parsing by humans (even if they speak dutch). +I guess we'd prefer something like (2) or (3). + +@item +Please don't run make po/po-update with GNU gettext < 0.10.35 + +@end itemize diff --git a/Documentation/user/lilypond.tely b/Documentation/user/lilypond.tely index ccb2641060..88b3b59f16 100644 --- a/Documentation/user/lilypond.tely +++ b/Documentation/user/lilypond.tely @@ -100,6 +100,8 @@ this and other documentation. @c Move to Reference Manual? * Internals:(lilypond-internals). Auto generated detailed documentation. * convert-ly:: Upgrading input files. +* Internals:: +* Development:: Some hints on developing for LilyPond. * Index:: Unified index. @end menu @@ -126,6 +128,8 @@ this and other documentation. @include convert-ly.itexi +@include development.itexi + @node Index, , , Top @unnumbered Index diff --git a/Documentation/user/refman.itely b/Documentation/user/refman.itely index 55cd7287c8..60018dacba 100644 --- a/Documentation/user/refman.itely +++ b/Documentation/user/refman.itely @@ -39,8 +39,6 @@ * contextdefs:: contextdefs * Sound output:: Sound output * midilist:: midilist -* Grobs:: Graphical objects -* Molecule:: Molecules * Pre-defined Identifiers:: Pre-defined Identifiers @c May be fragile. Better make single link to generated doco? * Interpretation contexts:(lilypond-internals)LilyPond interpretation contexts. @@ -693,8 +691,8 @@ You can alter the length of duration by writing appearance of note heads or rests. -Rests are entered like notes, with note name `@code{r}@indexcode{r}', -or `@code{R}@indexcode{R}'. There is also a note name +Rests are entered like notes, with note name `@code{r}@indexcode{r}', or +`@code{R}@indexcode{R}'. There is also a note name `@code{s}@indexcode{s}', which produces a space of the specified duration. `@code{R}' is specifically meant for entering parts: the @code{R} rest can expand to fill a score with rests, or it can be @@ -705,6 +703,10 @@ You can control the expansion by setting the property empty measures, and the multimeasure rests automatically adds the appropriate number. +Note that there is currently no way to condense multiple rests into a +single multimeasure rest. + + @cindex lyrics expressions @@ -2017,10 +2019,10 @@ A context is an object that holds the reading state of the expression; it contains information like @itemize @bullet - @item What notes are playing at this point? - @item What symbols will be printed at this point? - @item In what style will they printed? - @item What is the current key signature, time signature, point within + @item What notes are playing at this point? + @item What symbols will be printed at this point? + @item In what style will they printed? + @item What is the current key signature, time signature, point within the measure, etc.? @end itemize @@ -2136,16 +2138,6 @@ sequential music is also the default @code{Voice} context. The @code{d4} gets interpreted in the same context as @code{c4}. - - -These are the contexts supplied with the package. They are defined -in the initialization file @file{ly/engraver.ly}. - -@table @samp -@end table - - - Properties that are set in one context are inherited by all of the contained contexts. This means that a property valid for the @code{Voice} context can be set in the @code{Score} context (for @@ -2156,33 +2148,18 @@ corresponding to the appropriate context. In this case, the syntax is @example - @var{propname} @code{=} @var{value} @end example This assignment happens before interpretation starts, so a @code{\property} expression will override any predefined settings. -The @code{\property} expression will create any property you specify. -There is no guarantee that a property will be used. So if you spell -a property name wrong, there will be no error message. - The property settings are used during the interpretation phase. They are read by the LilyPond modules where interpretation contexts are built of. These modules are called @emph{translators}. Translators for notation are called @emph{engravers}, and translators for sound are called @emph{performers}. -The precise result of a property is determined by the implementation -of the translator that reads them. Therefore, the result of a -property can vary, since it is implementation and configuration -dependent. - -In order to fully find out what properties are used, you must -currently search the source code for calls to @code{get_property}. -The rest of the section is devoted to an (incomplete) overview of -available properties. - @mbinclude properties.itely @node Notation output definitions, , , Reference Manual @@ -2200,7 +2177,6 @@ The most important output definition is the @code{\paper} block, for music notation. The syntax is @example - @code{\paper @{} [@var{paperidentifier}] @var{items} @code{@}} @end example @@ -2213,9 +2189,13 @@ where each of the items is one of @item A context definition. See section @ref{contextdefs} for more information on context definitions. - @item - FIXME now in SCM +@ignore + + FIXME + + @item + A margin shape declaration. The syntax is @example @@ -2232,15 +2212,15 @@ where each of the items is one of the successive pairs of dimensions. The last pair of dimensions will define the characeristics of all lines beyond those explicitly specified. +@end ignore @item \stylesheet declaration. Its syntax is @example - \stylesheet @var{scm} + \stylesheet @var{alist} @end example - - See font.scm for details of @var{scm} + See @file{font.scm} for details of @var{alist}. @end itemize @@ -2274,17 +2254,7 @@ select. @node Paper variables, , , Reference Manual -There is a large number of paper variables that are used to control -details of the layout. These variables control the defaults for the -entire score. Usually, they do not have to be changed; they are by -default set to values that depend on the font size in use. The -values are used by the graphic objects while formatting the score; -they are therefore implementation dependent. Most variables are -accompanied by documentation in the initalization file -@file{params.ly} or @file{paperSZ.ly}, where @code{SZ} is the staff -height in points. - -Nevertheless, here are some variables you may want to use or change: +The paper block has some variables you may want to use or change: @table @samp @item @code{indent}@indexcode{indent} @@ -2313,7 +2283,8 @@ Nevertheless, here are some variables you may want to use or change: Defaults to 0. @item @code{stafflinethickness}@indexcode{stafflinethickness} - Determines the thickness of staff and bar lines. + Determines the thickness of staff lines, and also acts as a scaling +parameter for other line thicknesses. @end table @@ -2393,8 +2364,12 @@ one of @item @code{\accepts} @var{contextname} @code{;} Add @var{contextname} to the list of context this context can - contain. The first listed context the context to create by + contain. The first listed context is the context to create by default. + + @item @code{\denies}. The opposite of @code{\accepts}. Added for +completeness, but is never used in practice. + @item @code{\remove} @var{engravername} @code{;} Remove a previously added (with @code{\consists}) engraver. @@ -2487,10 +2462,8 @@ translator: @node Sound output, , , Reference Manual @section Sound output - - -The MIDI block is analogous to the paper block, but it is simpler. -The @code{\midi} block can contain: +The MIDI block is analogous to the paper block, but it is somewhat +simpler. The @code{\midi} block can contain: @cindex MIDI block @itemize @bullet @@ -2630,284 +2603,3 @@ provide shorthands for some settings. Most of them are in @end table -@node Grobs, , , Reference Manual -@section Grobs - -This section is about Grobs (short for Graphical Objects), which are -formatting objects used to create the final output. This material is -normally the domain of LilyPond gurus, but occasionally, a normal user -also has to deal with grobs. - -The most simple interaction with Grobs are when you use -@code{\override}: - -@example - \property Voice.Stem \override #'direction = #1 -@end example - -This piece of lily input causes all stem objects to be stem-up -henceforth. In effect, you are telling lilypond to extend the defintion -of the "Stem" grob with the setting @code{direction := 1}. Of course -there are many more ways of customizing Lily output, and since most of -them involve Grobs in some form, this section explains some details of -how grobs work. - -@menu -* What is a grob?:: -* Callbacks:: -* Setting grob properties:: -* Items and Spanners:: -* Pointer substitution:: -@end menu - -@node What is a grob?, , , Grobs - -All grobs have an X and Y-position on the page. These X and Y positions -are stored in a relative format, so they can easily be combined by -stacking them, hanging one grob to the side of another, and coupling -them into a grouping-grob. - -Each grob has a reference point, or parent: the position of a grob is -stored relative to that reference point. For example the X-reference -point of a staccato dot usually is the note head that it applies -to. Whenever the note head is moved, the staccato dot moves along -automatically. - -If you keep following offset reference points, you will always end up at -the root-object. This root object is called @code{Line_of_score} -@ref{(lilypond-internals)Element Line_of_score}, and it represents a -system (ie. a line of music). - -All grobs carry a set of grob-properties. In the Stem example above, -the property @code{direction} is set to value @code{1}. The function -that draws the symbol (@code{Stem::brew_molecule}) uses the value of -@code{direction} to determine how to print the stem and the flag. The -appearance of a grob is determined solely by the values of its -properties. - -Often, a grob also is associated with a symbol. On the other hand, Some -grobs do not print any symbols, but take care of grouping objects. For -example, there is a separate grob that stacks staffs vertically, so they -are not printed in overstrike. The NoteCollision @ref{(lilypond-internals)Element -NoteCollision} is another example of an abstract grob. It only moves -around chords, but doesn't print anything. - -A complete list of grob types is found in @ref{(lilypond-internals)Elements} - -Grobs are created in the "Interpreting music" phase, by things in -LilyPond called engravers. In this phase of the translation, a load of -grobs are created, and they are linked into a giant network of objects. -This network of grobs forms the "specification" of the print -problem. This problem is then solved: configurations, directions, -dimensions, line breaks, etc. are calculated. Finally, the printing -description in the form of Molecules (@ref{Molecule}) is extracted from -the network. These are then dumped into the output file - -@node Callbacks, , , Grobs - -Offsets of grobs are relative to a parent reference point. Most -positions are not known when an object is created, so these are -calculated as needed. This is done by adding a callback for a specific -direction. - -Suppose you have the following code in a .ly file. -@example - #(define (my-callback gr axis) - (* 2.0 (get-gr-property grob 'direction)) - ) - -.... - - \property Voice.Stem \override #'Y-offset-callbacks = #(list - my-callback) -@end example - -When the Y-offset of a Stem object is needed, LilyPond will -automatically execute all callbacks for that object. In this case, it -will find @code{my-callback}, and execute that. The result is that the -stem is translated by two staff spaces in its direction. - -(note: Y-offset-callbacks is also a property) - - -Offset callbacks can be stacked, ie. - -@example - \property .... \override #'Y-offset-callbacks = #(list - callback1 callback2 callback3) - -@end example - -The callbacks will be executed in the order callback3 callback2 -callback1. This is used for quantized positioning: the staccato dot is -above or below a note head, and it must not be on a staff-line. - -To achieve this, for the staccato there are two callbacks: one callback -that positions the grob above or below the note head, and one callback -that rounds the Y-position of the grob to the nearest open space. - -Similarly, the size of a grob are determined through callbacks, settable -with grob properties @code{X-extent-callback} and @code{Y-extent-callback}. -There can be only one extent-callback for each axis. No callback (value #f) -means: "empty in this direction". If you fill in a pair, that pair -hard-codes the extent in that coordinate. - - -@node Setting grob properties, , , Grobs - -Grob properties are stored as GUILE association lists, with symbols as -keys. From C++, element properties can be accessed using the functions - -@example - SCM get_grob_property (SCM) const; - void set_grob_property (const char * , SCM val); - void set_immutable_grob_property (const char * , SCM val); - void set_immutable_grob_property (SCM key, SCM val); - void set_grob_property (SCM , SCM val); - void set_grob_pointer (const char*, SCM val); - SCM remove_grob_property (const char* nm); -@end example - -In GUILE, LilyPond provides - -@example - ly-get-grob-property GROB SYMBOL - ly-set-grob-property GROB SYMBOL VALUE -@end example - -All lookup functions identify undefined properties with -end-of-list (ie. @code{'()} in Scheme or @code{SCM_EOL} in C) - -Properties are stored in two ways: -@itemize @bullet -@item mutable properties: -element properties that change from object to object. The storage of -these are private to a grob. Typically this is used to store lists of -pointers to other grobs - -@item immutable properties: -element properties that are shared across different grobs of the same -type. The storage is shared, and hence it is read-only. Typically, this -is used to store function callbacks, and values for shared element -properties are read from @file{scm/element-description.scm}. -@end itemize - -There are two ways to manually set grob properties. - -You can change immutable grob properties. This is done with the -\override syntax: - -@example - \property Voice.Stem \override #'direction = #1 -@end example - -This will push the entry @code{'(direction . 1)} on the immutable -property list for stems, in effect overriding the setting from -@file{scm/element-description.scm}. This can be undone by - -@example - \property Voice.stem \revert #'direction -@end example - -If you use this a lot, this gets old quickly. So we also have a -shorthand, - -@example - \property Context.GrobType \set #'prop = #VAL -@end example - -this does a @code{\revert} followed by a @code{\override} - -The second way is \outputproperty. This construct looks like - -@example - \context ContextName \outputproperty @var{pred} #@var{sym} = #@var{val} -@end example - -In this case, in every grob that satisfies @var{pred}, the property -assignment @var{sym} = @var{val} is done. For example - -@example - \outputproperty - #(lambda (gr) (string? (ly-get-grob-property gr - 'text))) - #'extra-offset = #'(-1.0 . 0.0) -@end example - -This shifts all elements that have a @code{text} property one staff -space to the left. This mechanism is rather clumsy to use, but it allows -you tweak any setting of any grob. - -@node Items and Spanners, , , Grobs -@unnumberedsubsec Items and Spanners - -Grobs can also be distinguished in their role in the horizontal spacing. -A lot of grobs define constraints on the spacing by their sizes. For -example, note heads, clefs, stems, and all other symbols with a fixed -shape. These grobs form a subtype called @code{Item}. - -Other grobs have a shape that depends on the horizontal spacing. For -example, slur, beam, tie, etc. These grobs form a subtype called -@code{Spanner}. All spanners have two span-points (these must be -@code{Item}s), one on the left and one on the right. The left bound is -also the X-reference point. - -Some items need special treatment for line breaking. For example, a -clef is normally only printed at the start of a line (ie. after a line -break). To model this, `breakable' items (clef, key signature, bar lines, -etc.) are copied twice. Then we have three versions of each breakable -item: one version if there is no line break, one version that is printed -before the line break (at the end of a system), one version that is -printed after the line break. - -Whether these versions are visible and take up space, is determined by -the outcome of the visibility-lambda. This is a function taking a -direction (-1, 0 or 1) and returns a cons of booleans, signifying wether -this grob should be transparent and invisible. - -@node Pointer substitution, , , Grobs -@unnumberedsubsec Pointer substitution - - -Symbols that cross line-breaks (such as slurs) cause some more -complications. When a spanner crosses a line-break, then the spanner is -"broken into pieces", for every line that the spanner is in, a copy of -the grob is made. A substitution process redirects all grob-reference -so that spanner grob will only reference other grobs in the same line. - -@node Molecule, , , Reference Manual - -The objective of any typesetting system is to put ink on paper in the -right places. For LilyPond, this final stage is left to the TeX and the -printer subsystem. For lily, the last stage in processing a score is -outputting a description of what to put where. This description roughly -looks like - -@example - PUT glyph AT (x,y) - PUT glyph AT (x,y) - PUT glyph AT (x,y) -@end example - -you merely have to look at the tex output of lily to see this. -Internally these instructions are encoded in Molecules:@footnote{At some -point LilyPond also contained Atom-objects, but they have been replaced -by Scheme expressions.}. A molecule is an object that combines -dimension information (how large is this glyph ?) with -what-to-print-where. - -Conceptually, Molecules can be constructed from Scheme code, by -translating a Molecule and by combining two molecules. In BNF notation: - -@example - Molecule = COMBINE Molecule Molecule - | TRANSLATE Offset Molecule - | GLYPH-DESCRIPTION - ; -@end example - -(refer to the C++ code for more details). All visible, -ie. non-transparent, grobs have a callback to create a Molecule. The -name of the property is @code{molecule-callback}, and its value should -be a Scheme function taking one argument (the grob) and returning a -Molecule. diff --git a/lily/include/engraver.hh b/lily/include/engraver.hh index a87cbbc811..729c5d7d57 100644 --- a/lily/include/engraver.hh +++ b/lily/include/engraver.hh @@ -25,11 +25,8 @@ class Engraver : public virtual Translator { friend class Engraver_group_engraver; protected: - /// utility - // Paper_def * paper_l() const; - /* - Call this last thing. + Call this when you're finished with ELEM_P. */ virtual void typeset_grob (Grob*elem_p); /* -- 2.39.5