]> git.donarmstrong.com Git - lilypond.git/commitdiff
lilypond-1.3.116
authorfred <fred>
Wed, 27 Mar 2002 00:34:33 +0000 (00:34 +0000)
committerfred <fred>
Wed, 27 Mar 2002 00:34:33 +0000 (00:34 +0000)
Documentation/GNUmakefile
Documentation/regression-test.tely
Documentation/user/GNUmakefile
Documentation/user/refman.itely
VERSION
lily/paper-outputter.cc
lily/text-spanner.cc
scm/translator-description.scm
scripts/lilypond-book.py

index 1b3462f69348b99ee79cf160b73745f460c22fcf..3a21d70c30803dbf34b97cf9396c1277b77b7418 100644 (file)
@@ -12,6 +12,10 @@ include $(depth)/make/stepmake.make
 
 default: local-doc
 
+test-reg:
+       rm -f out-www/regression-test.html out-www/regression-test.texi 
+       $(MAKE) out=www out-www/regression-test.html
+
 local-WWW: copy-for-me txt-to-html $(outdir)/regression-test.ps.gz $(outdir)/regression-test.html footify
 
 copy-for-me:
index b2d8b87c0b1d797253e509207b9cb34392f2af5c..98d6a1b34d899c03003184f5dc3fff2e740cb61e 100644 (file)
@@ -61,6 +61,8 @@ and documenting bugfixes.
 
 @lilypondfile{glissando.ly}
 
+@lilypondfile{follow-thread.ly}
+
 
 
 @section Chord names
@@ -83,6 +85,10 @@ and documenting bugfixes.
 
 @lilypondfile{beam-position.ly}
 
+@lilypondfile{auto-beam-bar.ly}
+
+@lilypondfile{beam-rest.ly}
+
 @lilypondfile{slur-nice.ly}
 @lilypondfile{slur-symmetry.ly}
 @lilypondfile{slur-symmetry-1.ly}
index 906ea48fb58a09f5fcd4cb8010e1ee6277ed5f7e..e1b1d32f0d0e5d5ce2c461129d2b7688068bc5f2 100644 (file)
@@ -18,7 +18,7 @@ PS_FILES = $(DVI_FILES:.dvi=.ps)  $(OUTDOC_FILES:.doc=.ps) $(OUTTEX_FILES:.tex=.
 
 PS_GZ_FILES= $(addsuffix .gz, $(PS_FILES))
 
-INFO_FILES = $(addprefix $(outdir)/, lilypond.info lilypond-internals.info)
+INFO_FILES = $(addprefix $(outdir)/, lilypond.info lilypond-internals.info)
 
 STEPMAKE_TEMPLATES=tex texinfo documentation
 LOCALSTEPMAKE_TEMPLATES=lilypond ly
index 92b5299069095185e802473f3b35b8d77221d935..90e9e53e42441d1174090dbc90c6e4ac77602e1f 100644 (file)
@@ -40,6 +40,7 @@
 * 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.
@@ -2616,6 +2617,7 @@ 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
@@ -2636,17 +2638,218 @@ 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.
 
-Types of grob?
+@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.
+
+@node Items and Spanners, , , Grobs
 
-What is a grob?
+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}.
 
-Where do they come from?
+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.
 
-How can you override?
+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.
 
-Items and Spanners?
+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.
 
-X and Y parents, offsets and extents.
+@node Pointer substitution, , , Grobs
 
 
 @node Molecule, , , Reference Manual
@@ -2667,7 +2870,8 @@ 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 ?) with what-to-print-where.
+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:
@@ -2680,4 +2884,7 @@ translating a Molecule and by combining two molecules. In BNF notation:
 @end example
 
 (refer to the C++ code for more details). All visible,
-ie. non-transparent, grobs have a function to create Molecule.
+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/VERSION b/VERSION
index b94cd0f76c0ba9e25bff2be4e523826adde4381e..07b942cf3e889f99afdc646d13635b93504c3495 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1,7 +1,7 @@
 PACKAGE_NAME=LilyPond
 MAJOR_VERSION=1
 MINOR_VERSION=3
-PATCH_LEVEL=115
+PATCH_LEVEL=116
 MY_PATCH_LEVEL=
 
 # use the above to send patches: MY_PATCH_LEVEL is always empty for a
index 781215c2002df99c6e0fe170a3716b53eb1cbf23..0bf6c9db9811a304153d23baa483a79288991c7b 100644 (file)
@@ -273,12 +273,15 @@ Paper_outputter::output_score_header_fields (Paper_def *paper)
       for (int i = 0; i < global_score_header_fields.size (); i++)
        {
          String key = global_score_header_fields[i];
-         //      SCM val = gh_assoc (ly_str02scm (key.ch_C ()), fields);
          SCM val = gh_assoc (ly_symbol2scm (key.ch_C ()), fields);
          String s;
+         /* Only write header field to file if it exists */
          if (gh_pair_p (val))
-           s = ly_scm2string (gh_cdr (val));
-         output_score_header_field (base, key, s);
+           {
+             s = ly_scm2string (gh_cdr (val));
+             /* Always write header field file, even if string is empty ... */
+             output_score_header_field (base, key, s);
+           }
        }
     }
 }
index c83551e5569856327078f1e18cbd47f8dd15447d..5280703bad0312a91a0439951c513f12959b9249 100644 (file)
@@ -24,7 +24,6 @@
     - contination types (vert. star, vert. end)  |-> eat volta-spanner
     - more styles
     - more texts/positions
-    - style: hairpin ?
  */
 
 MAKE_SCHEME_CALLBACK (Text_spanner, brew_molecule, 1);
@@ -35,22 +34,42 @@ Text_spanner::brew_molecule (SCM smob)
   Grob *me= unsmob_grob (smob);
   Spanner *spanner = dynamic_cast<Spanner*> (me);
 
-  Real staff_space = Staff_symbol_referencer::staff_space (me);
-  
+
+
+  /* Ugh, must be same as Hairpin::brew_molecule.  */
+  Real padding = gh_scm2double (me->get_grob_property ("padding"));
+  Real broken_left =  spanner->get_broken_left_end_align ();
+  Real width = spanner->spanner_length ();
+  width -= broken_left;
+
   Drul_array<bool> broken;
+  Drul_array<Real> extra_off;
   Direction d = LEFT;
   do
     {
-      Paper_column* s = dynamic_cast<Paper_column*>(spanner->get_bound (d)); // UGH
-      if (s && s->musical_b ())
-       broken[d] = false;
-      else
-       broken[d] = true;
+      Item *b = spanner->get_bound (d);
+      broken[d] = b->break_status_dir () != CENTER;
+
+      if (!broken [d])
+       {
+
+         Interval e = b->extent (b, X_AXIS);
+         Real r = 0.0;
+         if (!e.empty_b ())
+           r = e[-d] + padding;
+         width += d * r;
+         extra_off[d] = r;
+       }
     }
   while (flip (&d) != LEFT);
-  
-  SCM properties = Font_interface::font_alist_chain (me);
 
+  // FIXME: ecs tells us
+  width += gh_scm2double (me->get_grob_property ("width-correct"));
+  /* /Ugh */
+
+
+  SCM properties = Font_interface::font_alist_chain (me);
+  
   SCM edge_text = me->get_grob_property ("edge-text");
   Drul_array<Molecule> edge;
   if (gh_pair_p (edge_text))
@@ -65,6 +84,8 @@ Text_spanner::brew_molecule (SCM smob)
        }
       while (flip (&d) != LEFT);
     }
+  width -= edge[LEFT].extent (X_AXIS).length ()
+    + edge[RIGHT].extent (X_AXIS).length ();
 
   Drul_array<Real> shorten;
   shorten[LEFT] = 0;
@@ -73,19 +94,12 @@ Text_spanner::brew_molecule (SCM smob)
   SCM s = me->get_grob_property ("shorten");
   if (gh_pair_p (s))
     {
-      shorten[LEFT] = gh_scm2double (gh_car (s)) * staff_space;
-      shorten[RIGHT] = gh_scm2double (gh_cdr (s)) * staff_space;
+      shorten[LEFT] = gh_scm2double (gh_car (s));
+      shorten[RIGHT] = gh_scm2double (gh_cdr (s));
     }
 
-  Real broken_left =  spanner->get_broken_left_end_align ();
-  Real width = spanner->spanner_length ();
-  Grob *bnd = spanner->get_bound (RIGHT);
-  width += bnd->extent (bnd, X_AXIS).length ();
-  width -= broken_left;
   width -= shorten[LEFT] + shorten[RIGHT];
-  width -= edge[LEFT].extent (X_AXIS).length ()
-    + edge[RIGHT].extent (X_AXIS).length ();
-
+  
   if (width < 0)
     {
       warning (_ ("Text_spanner too small"));
@@ -138,7 +152,7 @@ Text_spanner::brew_molecule (SCM smob)
     m.add_at_edge (X_AXIS, RIGHT, edge_line[RIGHT], 0);
   if (!edge[RIGHT].empty_b ())
     m.add_at_edge (X_AXIS, RIGHT, edge[RIGHT], 0);
-  m.translate_axis (broken_left, X_AXIS);
+  m.translate_axis (broken_left + extra_off[LEFT], X_AXIS);
 
   return m.smobbed_copy ();
 }
index 879b4ff09037fd16a426b4f0577975a8a75a0e2c..77a42612e892ddd56a0e0259e7c018c1959ada07 100644 (file)
@@ -204,7 +204,7 @@ put on top of all staffs, and appears only at  left side of the staff."
     'Break_align_engraver
     (engraver-description
      "Break_align_engraver"
-     "Align graphic elements with corresponding break-align-symbols into groups, and order the groups according to breakAlignOrder"
+     "Align grobs with corresponding break-align-symbols into groups, and order the groups according to breakAlignOrder"
      '(BreakAlignment BreakAlignGroup LeftEdge)
      '(
       breakAlignOrder
@@ -285,7 +285,7 @@ If omitted, then dots appear on top of the notes.
      "Dynamic_engraver"
      ""
      '(DynamicLineSpanner
-       DynamicText Crescendo
+       DynamicText Hairpin
        TextSpanner)
      '(
       )))
@@ -484,7 +484,7 @@ making a single line staff that demonstrates the rhythm of a melody."
     (engraver-description
      "Property_engraver"
 "This is a engraver that converts \property settings into
-back-end element-property settings. Example: Voice.stemLength will set
+back-end grob-property settings. Example: Voice.stemLength will set
 #'length in all Stem objects.
 
 Due to CPU and memory requirements, the use of this engraver is deprecated."
index 763aa79fa148b90ab29e586aafe4df11946d9f46..4d6b0e58f83601d6ea478becec9584244d4f7851 100644 (file)
@@ -348,7 +348,6 @@ output_dict= {
 # should also support fragment in
                  
                  'output-all': r"""
-@include %(fn)s.texidoc
 @tex
 \catcode`\@=12
 \input lilyponddefs
@@ -776,7 +775,7 @@ def schedule_lilypond_block (chunk):
                needed_filetypes.append('png')
        if 'eps' in opts and not ('eps' in needed_filetypes):
                needed_filetypes.append('eps')
-       outname = os.path.join(g_outdir, basename)
+       pathbase = os.path.join (g_outdir, basename)
        def f(base, ext1, ext2):
                a = os.path.isfile(base + ext2)
                if (os.path.isfile(base + ext1) and
@@ -786,11 +785,11 @@ def schedule_lilypond_block (chunk):
                                not os.path.isfile(base + ext2):
                        return 1
        todo = []
-       if 'tex' in needed_filetypes and f(outname, '.ly', '.tex'):
+       if 'tex' in needed_filetypes and f(pathbase, '.ly', '.tex'):
                todo.append('tex')
-       if 'eps' in needed_filetypes and f(outname, '.tex', '.eps'):
+       if 'eps' in needed_filetypes and f(pathbase, '.tex', '.eps'):
                todo.append('eps')
-       if 'png' in needed_filetypes and f(outname, '.eps', '.png'):
+       if 'png' in needed_filetypes and f(pathbase, '.eps', '.png'):
                todo.append('png')
        newbody = ''
        if 'verbatim' in opts:
@@ -806,8 +805,10 @@ def schedule_lilypond_block (chunk):
                else:
                        s = 'output-tex'
        else: # format == 'texi'
-               s = 'output-all'
-       newbody = newbody + get_output(s) % {'fn': basename }
+               if os.path.isfile (pathbase + '.texidoc'):
+                       newbody = newbody + '\n@include %s.texidoc' % basename
+               s = 'output-all'
+       newbody = newbody + get_output (s) % {'fn': basename }
        return ('lilypond', newbody, opts, todo, basename)
 
 def process_lilypond_blocks(outname, chunks):#ugh rename