about nested tuplets. Remove BUG.
* input/regression/tuplet-nest.ly: update: remove manual hack.
* lily/tuplet-bracket.cc (print): use robust_scm2drul
(print): manually call print() for subtuplets.
(calc_position_and_height): add subtuplets to the
support. Vertically shift outer tuplet
* ly/engraver-init.ly (RemoveEmptyRhythmicStaffContext): set
remove-first for Lyrics, ChordNames and FiguredBass
* scm/define-grob-properties.scm (all-internal-grob-properties):
use ly:grob-array? iso. grob-list?
(all-internal-grob-properties): add tuplets grob-array.
* lily/tuplet-bracket.cc (add_tuplet_bracket):
new function
+2005-08-03 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * Documentation/user/basic-notation.itely (Tuplets): add note
+ about nested tuplets. Remove BUG.
+
+ * input/regression/tuplet-nest.ly: update: remove manual hack.
+
+ * lily/tuplet-bracket.cc (print): use robust_scm2drul
+ (print): manually call print() for subtuplets.
+ (calc_position_and_height): add subtuplets to the
+ support. Vertically shift outer tuplet
+
+ * ly/engraver-init.ly (RemoveEmptyRhythmicStaffContext): set
+ remove-first for Lyrics, ChordNames and FiguredBass
+
+ * scm/define-grob-properties.scm (all-internal-grob-properties):
+ use ly:grob-array? iso. grob-list?
+ (all-internal-grob-properties): add tuplets grob-array.
+
+ * lily/tuplet-bracket.cc (add_tuplet_bracket):
+ new function
+
+2005-08-03 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * input/test/time-signature-staff.ly: new file.
+
+ * ly/declarations-init.ly (center): escape to Scheme. Fixes
+ spurious #<Music FingerEvent> errors. Backportme.
+
2005-08-03 Mats Bengtsson <mabe@drongo.s3.kth.se>
* Documentation/user/programming-interface.itely (Markup
@itemize @bullet
+@item
+Nested tuplets are automatically positioned,
+
+@lilypond[fragment,raggedright,verbatim,relative=2]
+\set tupletNumberFormatFunction = #fraction-tuplet-formatter
+\times 4/6 {
+ a4 a
+ \times 3/5 { a a a a a }
+}
+@end lilypond
+
+This feature was sponsored by Trevor Baca.
+
@item
Music expressions can be displayed, in LilyPond notation, using the
new @code{\displayLilyMusic} function. For instance:
g'4 \times 2/3 {c'4 c' c'} d'4 d'4
@end lilypond
+Tuplets may be nested, for example,
+
+@lilypond[fragment,raggedright,verbatim,relative=2]
+\set tupletNumberFormatFunction = #fraction-tuplet-formatter
+\times 4/6 {
+ a4 a
+ \times 3/5 { a a a a a }
+}
+@end lilypond
+
@refcommands
@cindex @code{\tupletUp}
instead.
+
+
+
@seealso
Program reference: @internalsref{TupletBracket}, and @internalsref{TimeScaledMusic}.
+Examples: @inputfileref{input/@/regression,tuplet@/-nest@/.ly}.
-@refbugs
-
-Nested tuplets are not formatted automatically. In this case, outer
-tuplet brackets should be moved manually, which is demonstrated in
-@inputfileref{input/@/regression,tuplet@/-nest@/.ly}.
@node Scaling durations
D. Josiah Boothby
Nancho Alvarez
Sven Axelsson
-
+Trevor Baca
BUG HUNTERS/SUGGESTIONS
\version "2.6.0"
-
\header {
-
- texidoc=" Nested tuplets can be printed, using a manual hack to
- move the outer bracket up."
-
+ texidoc=" Tuplets may be nested."
}
-#(define (make-text-checker-once text)
- (lambda (grob) (and text-checker-once
- (if (equal? text (ly:grob-property grob 'text))
- (begin
- (set! text-checker-once #f) #t)
- #f))))
-
-#(define text-checker-once #t)
-
-\score {
- \relative c'' {
+\paper {
+ raggedright = ##t
+ indent = 0.0
+}
- \set tupletNumberFormatFunction = #fraction-tuplet-formatter
+\relative c'' {
+ \set tupletNumberFormatFunction = #fraction-tuplet-formatter
+ \times 4/6 {
+ \times 2/3 {
+ a a a
+ }
+ \times 3/5 {
+ a a a a a
+ }
+ }
- \applyoutput #(lambda (gr org cur)
- (if (equal? (ly:grob-property gr 'text) "6:4")
- (set! (ly:grob-property gr 'extra-offset) '(0 . 1.5))))
- \times 4/6 {
- \times 2/3 {
- a a a
- }
- \times 3/5 {
- a a a a a
- }
+ s1*1/6
+
+ \stemUp
+ \times 4/6 {
+ \times 2/3 {
+ a1*1/6 a f'
+ }
+ \times 3/5 {
+ c f g a b
}
}
- \layout { raggedright = ##t}
+
}
--- /dev/null
+%% todo: move into advanced notation section of the manual.
+
+\header {
+
+ texidoc = "Time signatures may be put on a separate staff. This is
+ used contemporary pieces with many time signature changes. "
+
+}
+\version "2.6.0"
+\layout {
+ raggedright = ##T
+}
+
+\layout{
+ \context {
+ \type "Engraver_group_engraver"
+ \consists "Time_signature_engraver"
+ \consists "Axis_group_engraver"
+ \name "TimeSig"
+ \override TimeSignature #'font-size = #4
+ }
+ \context {
+ \Score \accepts TimeSig
+ }
+
+ \context { \Staff
+ \override TimeSignature #'transparent = ##t
+ }
+}
+
+
+\relative
+<< \new Staff { \time 2/4 c2 \time 3/4 c2. \time 4/4 c1 }
+ \new TimeSig {
+ \skip 4 * 9
+ }
+ \new Staff { r4 r r
+ r4 r r
+ r4 r r }
+
+ >>
SCM
properties_to_font_size_family (SCM fonts, SCM alist_chain)
{
- return scm_call_2 (ly_lily_module_constant ("lookup-font"), fonts, alist_chain);
+ return scm_call_2 (ly_lily_module_constant ("lookup-font"), fonts,
+ alist_chain);
}
Font_metric *
DECLARE_SCHEME_CALLBACK (print, (SCM));
static bool has_interface (Grob *);
+ static void add_tuplet_bracket (Grob *me, Grob *smaller_bracket);
+ static void get_bounds (Grob *,Grob **,Grob **);
static void add_column (Grob *me, Item *);
static void add_beam (Grob *me, Grob *);
static Grob *parallel_beam (Grob *me, Link_array<Grob> const &cols, bool *equally_long);
static Real get_duration_space (Grob *, Moment dur, Rational shortest, bool *);
static Rational find_shortest (Grob *, Link_array<Grob> const &);
static void breakable_column_spacing (Grob *, Item *l, Item *r, Moment);
- static void find_loose_columns () {}
static void prune_loose_columns (Grob *, Link_array<Grob> *cols, Rational);
- static void find_loose_columns (Link_array<Grob> cols);
static void set_explicit_neighbor_columns (Link_array<Grob> const &cols);
static void set_implicit_neighbor_columns (Link_array<Grob> const &cols);
static void do_measure (Rational, Grob *me, Link_array<Grob> *cols);
Real increment = robust_scm2double (me->get_property ("spacing-increment"), 1.2);
for (int i = 0; i < cols->size (); i++)
{
- if (Item::is_breakable (cols->elem (i)) || Paper_column::is_musical (cols->elem (i)))
+ if (Item::is_breakable (cols->elem (i))
+ || Paper_column::is_musical (cols->elem (i)))
{
newcols.push (cols->elem (i));
continue;
SCM rp = me->get_property ("right-position");
if (!scm_is_number (rp) || !scm_is_number (lp))
- after_line_breaking (smob);
+ {
+ /*
+ UGH. dependency tracking!
+ */
+ extract_grob_set (me, "tuplets", tuplets);
+ for (int i = 0; i < tuplets.size (); i++)
+ Tuplet_bracket::print (tuplets[i]->self_scm());
+
+ after_line_breaking (smob);
+ }
}
Real ly = robust_scm2double (me->get_property ("left-position"), 0);
if (bracket_visibility)
{
- Real ss = Staff_symbol_referencer::staff_space (me);
Real gap = 0.;
if (!num.extent (X_AXIS).is_empty ())
gap = num.extent (X_AXIS).length () + 1.0;
- SCM fl = me->get_property ("bracket-flare");
- SCM eh = me->get_property ("edge-height");
- SCM sp = me->get_property ("shorten-pair");
-
- Direction d = LEFT;
- Drul_array<Real> height, flare, shorten;
- do
- {
- flare[d] = height[d] = shorten[d] = 0.0;
- if (is_number_pair (fl))
- flare[d] += ss * scm_to_double (index_get_cell (fl, d));
- if (is_number_pair (eh))
- height[d] += -dir * ss * scm_to_double (index_get_cell (eh, d));
- if (is_number_pair (sp))
- shorten[d] += ss * scm_to_double (index_get_cell (sp, d));
- }
- while (flip (&d) != LEFT);
-
+ Drul_array<Real> zero (0,0);
+ Real ss = Staff_symbol_referencer::staff_space (me);
+ Drul_array<Real> height
+ = robust_scm2drul (me->get_property ("edge-height"), zero);
+ Drul_array<Real> flare
+ = robust_scm2drul (me->get_property ("bracket-flare"), zero);
+ Drul_array<Real> shorten
+ = robust_scm2drul (me->get_property ("shorten-pair"), zero);
+
+ scale_drul (&height, -ss * dir);
+ scale_drul (&flare, ss);
+ scale_drul (&shorten, ss);
+
Stencil brack = make_bracket (me, Y_AXIS,
Offset (w, ry - ly),
height,
return m;
}
+void
+Tuplet_bracket::get_bounds (Grob *me, Grob **left, Grob **right)
+{
+ extract_grob_set (me, "note-columns", columns);
+ int l = 0;
+ while (l < columns.size () && Note_column::has_rests (columns[l]))
+ l++;
+
+ int r = columns.size ()- 1;
+ while (r >= l && Note_column::has_rests (columns[r]))
+ r--;
+
+ *left = *right = 0;
+
+ if (l <= r)
+ {
+ *left = columns[l];
+ *right = columns[r];
+ }
+}
+
+
/*
use first -> last note for slope, and then correct for disturbing
notes in between. */
void
-Tuplet_bracket::calc_position_and_height (Grob *me, Real *offset, Real *dy)
+Tuplet_bracket::calc_position_and_height (Grob *me_grob, Real *offset, Real *dy)
{
+ Spanner *me = dynamic_cast<Spanner*> (me_grob);
+
extract_grob_set (me, "note-columns", columns);
+ extract_grob_set (me, "tuplets", tuplets);
+
Grob *commony = common_refpoint_of_array (columns, me, Y_AXIS);
+ commony = common_refpoint_of_array (tuplets, commony, Y_AXIS);
Grob *commonx = common_refpoint_of_array (columns, me, X_AXIS);
+ commonx = common_refpoint_of_array (tuplets, commonx, Y_AXIS);
Interval staff;
if (Grob *st = Staff_symbol_referencer::get_staff_symbol (me))
/*
Use outer non-rest columns to determine slope
*/
- int l = 0;
- while (l < columns.size () && Note_column::has_rests (columns[l]))
- l++;
-
- int r = columns.size ()- 1;
- while (r >= l && Note_column::has_rests (columns[r]))
- r--;
-
- if (l < r)
+ Grob *left_col = 0;
+ Grob *right_col = 0;
+ get_bounds (me, &left_col, &right_col);
+ if (left_col && right_col)
{
- Interval rv = columns[r]->extent (commony, Y_AXIS);
- Interval lv = columns[l]->extent (commony, Y_AXIS);
+ Interval rv = right_col->extent (commony, Y_AXIS);
+ Interval lv = left_col->extent (commony, Y_AXIS);
rv.unite (staff);
lv.unite (staff);
Real graphical_dy = rv[dir] - lv[dir];
- Slice ls = Note_column::head_positions_interval (columns[l]);
- Slice rs = Note_column::head_positions_interval (columns[r]);
+ Slice ls = Note_column::head_positions_interval (left_col);
+ Slice rs = Note_column::head_positions_interval (right_col);
Interval musical_dy;
musical_dy[UP] = rs[UP] - ls[UP];
*dy = graphical_dy;
}
else
- * dy = 0;
+ *dy = 0;
*offset = -dir * infinity_f;
Real x1 = robust_relative_extent (rgr, commonx, X_AXIS)[RIGHT];
/*
- Slope.
+ offset
*/
Real factor = columns.size () > 1 ? 1 / (x1 - x0) : 1.0;
+ Array<Offset> points;
for (int i = 0; i < columns.size (); i++)
{
Interval note_ext = columns[i]->extent (commony, Y_AXIS);
Real notey = note_ext[dir] - me->relative_coordinate (commony, Y_AXIS);
Real x = columns[i]->relative_coordinate (commonx, X_AXIS) - x0;
- Real tuplety = *dy * x * factor;
+ points.push (Offset (x, notey));
+ }
+
+ /*
+ This is a slight hack. We compute two encompass points from the
+ bbox of the smaller tuplets.
+
+ We assume that the smaller bracket is 1.0 space high.
+ */
+
+ Real ss = Staff_symbol_referencer::staff_space (me);
+ for (int i = 0; i < tuplets.size (); i++)
+ {
+ Interval tuplet_x (tuplets[i]->extent (commonx, X_AXIS));
+ Interval tuplet_y (tuplets[i]->extent (commony, Y_AXIS));
- if (notey * dir > (*offset + tuplety) * dir)
- *offset = notey - tuplety;
+ Direction d = LEFT;
+ Real lp = scm_to_double (tuplets[i]->get_property ("left-position"));
+ Real rp = scm_to_double (tuplets[i]->get_property ("right-position"));
+ Real other_dy = rp - lp;
+
+ do
+ {
+ Real y =
+ tuplet_y.linear_combination (d * sign (other_dy));
+
+#if 0
+ /*
+ Let's not take padding into account for nested tuplets.
+ the edges can come very close to the stems, likewise for
+ nested tuplets?
+ */
+ Drul_array<Real> my_height
+ = robust_scm2drul (me->get_property ("edge-height"), Interval (0,0));
+ if (dynamic_cast<Spanner*> (tuplets[i])->get_bound (d)
+ == me->get_bound (d))
+ {
+ y += dir * my_height[d];
+ }
+#endif
+
+ points.push (Offset (tuplet_x[d] - x0, y));
+ }
+ while (flip (&d) != LEFT);
}
- // padding
+ for (int i = 0; i < points.size (); i++)
+ {
+ Real x = points[i][X_AXIS];
+ Real tuplety = *dy * x * factor;
+
+ if (points[i][Y_AXIS] * dir > (*offset + tuplety) * dir)
+ *offset = points[i][Y_AXIS] - tuplety;
+ }
+
*offset += scm_to_double (me->get_property ("padding")) * dir;
/*
horizontal brackets should not collide with staff lines.
+ Kind of pointless since we put them outside the staff anyway, but
+ let's leave code for the future when possibly allow them to move
+ into the staff once again.
*/
- Real ss = Staff_symbol_referencer::staff_space (me);
- if (*dy == 0 && fabs (*offset) < ss * Staff_symbol_referencer::staff_radius (me))
+ if (*dy == 0 &&
+ fabs (*offset) < ss * Staff_symbol_referencer::staff_radius (me))
{
// quantize, then do collision check.
*offset *= 2 / ss;
/*
We follow the beam only if there is one, and we are next to it.
*/
- Real dy, offset;
+ Real dy = 0.0;
+ Real offset = 0.0;
if (!par_beam
|| get_grob_direction (par_beam) != dir)
{
add_bound_item (dynamic_cast<Spanner *> (me), n);
}
+void
+Tuplet_bracket::add_tuplet_bracket (Grob *me, Grob *bracket)
+{
+ Pointer_group_interface::add_grob (me, ly_symbol2scm ("tuplets"), bracket);
+ me->add_dependency (bracket);
+}
+
+
+
ADD_INTERFACE (Tuplet_bracket,
"tuplet-bracket-interface",
"A bracket with a number in the middle, used for tuplets.",
"note-columns bracket-flare edge-height shorten-pair "
+ "tuplets "
"padding left-position right-position bracket-visibility "
"number-visibility thickness direction");
Music *music_;
Rational stop_;
Rational span_stop_;
+ Rational length_;
Spanner *spanner_;
Tuplet_description ()
{
music_ = 0;
spanner_ = 0;
}
+ static int compare (Tuplet_description const &a, Tuplet_description const &b)
+ {
+ return ::compare (a.length_, b.length_);
+ }
};
+
+
class Tuplet_engraver : public Engraver
{
public:
{
Tuplet_description d;
d.music_ = music;
- d.stop_ = now_mom ().main_part_ + music->get_length ().main_part_;
+ d.length_ = music->get_length ().main_part_;
+ d.stop_ = now_mom ().main_part_ + d.length_;
d.span_stop_ = d.stop_;
SCM s = get_property ("tupletSpannerDuration");
void
Tuplet_engraver::process_music ()
{
+ if (!tuplets_.size ())
+ return;
+
+
+ tuplets_.sort (&Tuplet_description::compare);
for (int i = 0; i < tuplets_.size (); i++)
{
if (tuplets_[i].spanner_)
tuplets_[i].music_->self_scm ());
tuplets_[i].spanner_ = spanner;
+ if (i > 0 && tuplets_[i-1].spanner_)
+ Tuplet_bracket::add_tuplet_bracket (tuplets_[i].spanner_, tuplets_[i-1].spanner_);
+ if (i < tuplets_.size()-1 && tuplets_[i+1].spanner_)
+ Tuplet_bracket::add_tuplet_bracket (tuplets_[i+1].spanner_, tuplets_[i].spanner_);
+
SCM proc = get_property ("tupletNumberFormatFunction");
if (ly_is_procedure (proc))
{
Tuplet_engraver::Tuplet_engraver ()
{
}
+
ADD_ACKNOWLEDGER (Tuplet_engraver,note_column);
ADD_TRANSLATOR (Tuplet_engraver,
/* descr */ "Catch Time_scaled_music and generate appropriate bracket ",
<c es ges beses>-\markup { \super "o7" }
}
-ignatzekExceptions = #(sequential-music-to-chord-exceptions
- ignatzekExceptionMusic #t)
-
partialJazzMusic = {
<c d>1-\markup { \normal-size-super "2" }
<c es>-\markup { "m" }
<c d es>-\markup { "m" }-\markup { \normal-size-super "sus2" }
}
+
%% TODO: compatibility ignatzek code
-fullJazzExceptions = #(sequential-music-to-chord-exceptions
- ignatzekExceptionMusic #f)
+fullJazzExceptions=
+#(sequential-music-to-chord-exceptions ignatzekExceptionMusic #f)
-partialJazzExceptions = #(sequential-music-to-chord-exceptions
- partialJazzMusic #f)
+partialJazzExceptions=
+#(sequential-music-to-chord-exceptions partialJazzMusic #f)
-
+ignatzekExceptions =
+#(sequential-music-to-chord-exceptions ignatzekExceptionMusic #t)
\include "script-init.ly"
% declarations for standard directions
-left = -1
-right = 1
-up = 1
-down = -1
-start = -1
-stop = 1
-smaller = -1
-bigger = 1
-center = 0
+left = #-1
+right = #1
+up = #1
+down = #-1
+start = #-1
+stop = #1
+smaller = #-1
+bigger = #1
+center = #0
%% FIXME
%% should also set allowBeamBreak, but how to do it "portably"? (ie. also
-foo = { \pageBreak }
-
\include "scale-definitions-init.ly"
melisma = #(make-span-event 'ManualMelismaEvent START)
\consists "Skip_event_swallow_translator"
\consists "Font_size_engraver"
\consists "Hara_kiri_engraver"
+ \override RemoveEmptyVerticalGroup #'remove-first = ##t
\override SeparationItem #'padding = #0.2
}
minimumVerticalExtent = #'(0 . 2.5)
extraVerticalExtent = ##f
\override SeparatingGroupSpanner #'padding = #0.8
+ \override RemoveEmptyVerticalGroup #'remove-first = ##t
verticalExtent = ##f
}
\consists "Skip_event_swallow_translator"
\consists "Separating_line_group_engraver"
\consists "Hara_kiri_engraver"
+ \override RemoveEmptyVerticalGroup #'remove-first = ##t
}
\context {
(axis-group-parent-X ,ly:grob? "Containing X axis group")
(axis-group-parent-Y ,ly:grob? "Containing Y axis group")
(accidental-grobs ,list? "Alist with (NOTENAME . GROBLIST) entries")
- (adjacent-hairpins ,grob-list? "List of directly neighboring hairpins")
+ (adjacent-hairpins ,ly:grob-array? "List of directly neighboring hairpins")
(after-line-breaking-callback ,procedure? "This procedure is called after line breaking. Its return value is ignored.")
- (all-elements ,grob-list? "list of all grobs in this line. Its
+ (all-elements ,ly:grob-array? "list of all grobs in this line. Its
function is to protect objects from being garbage collected.")
(arpeggio ,ly:grob? "pointer to arpeggio object.")
(beam ,ly:grob? "pointer to the beam, if applicable.")
(tie ,ly:grob? "")
(staff-symbol ,ly:grob? "the staff symbol grob that we're in.")
(rest ,ly:grob? "the staff symbol grob that we're in.")
- (rests ,grob-list? "A list of rest objects.")
+ (rests ,ly:grob-array? "A list of rest objects.")
(rest-collision ,ly:grob? "rest collision that a rest is in.")
(accidental-grob ,ly:grob? "Accidental for this note.")
- (bars ,grob-list? "list of bar line pointers.")
- (bounded-by-me ,grob-list? "list of spanners that have this
+ (bars ,ly:grob-array? "list of bar line pointers.")
+ (bounded-by-me ,ly:grob-array? "list of spanners that have this
column as start/begin point. Only columns that have grobs or act as bounds are spaced.")
- (columns ,grob-list? "list of grobs, typically containing
+ (columns ,ly:grob-array? "list of grobs, typically containing
paper-columns or note-column objects.")
- (conditional-elements ,grob-list? "Internal use only")
- (dependencies ,grob-list? "list of score-grob pointers that indicate who to compute first for certain global passes.")
- (encompass-objects ,grob-list? "Objects that a slur should avoid
+ (conditional-elements ,ly:grob-array? "Internal use only")
+ (dependencies ,ly:grob-array? "list of score-grob pointers that indicate who to compute first for certain global passes.")
+ (encompass-objects ,ly:grob-array? "Objects that a slur should avoid
in addition to notes and stems.")
- (elements ,grob-list? "list of grobs, type depending on the Grob where this is set in.")
- (heads ,grob-list? "List of note heads.")
- (items-worth-living ,grob-list? "A list of interesting items. If
+ (elements ,ly:grob-array? "list of grobs, type depending on the Grob where this is set in.")
+ (heads ,ly:grob-array? "List of note heads.")
+ (items-worth-living ,ly:grob-array? "A list of interesting items. If
empty in a particular staff, then that staff is erased.")
(details ,list? "alist of parameters for detailed grob behavior.")
- (note-heads ,grob-list? "List of note head grobs")
- (side-support-elements ,grob-list? "the support, a list of grobs.")
- (spacing-wishes ,grob-list? "List of note spacing or staff spacing objects.")
- (stems ,grob-list? "list of stem objects, corresponding to the notes that the arpeggio has to be before.")
+ (note-heads ,ly:grob-array? "List of note head grobs")
+ (side-support-elements ,ly:grob-array? "the support, a list of grobs.")
+ (spacing-wishes ,ly:grob-array? "List of note spacing or staff spacing objects.")
+ (stems ,ly:grob-array? "list of stem objects, corresponding to the notes that the arpeggio has to be before.")
+ (tuplets ,ly:grob-array? "list of smaller tuplet brackets")
-
- (left-neighbors ,grob-list? " List of
+ (left-neighbors ,ly:grob-array? " List of
spacing-wish grobs that are close to the current column.
The closest spacing-wishes determine the actual distances between the
columns.
")
- (right-neighbors ,grob-list? "see left-neighbors")
- (left-items ,grob-list? "")
- (right-items ,grob-list? "")
+ (right-neighbors ,ly:grob-array? "see left-neighbors")
+ (left-items ,ly:grob-array? "")
+ (right-items ,ly:grob-array? "")
(cause ,scheme? "Any kind of causation objects (i.e. music, or perhaps translator) that was the cause for this grob. ")
(font ,ly:font-metric? "Cached font metric object")
than a whole rest.")
- (spaceable-staves ,grob-list? "Objects to be spaced during page layout.")
+ (spaceable-staves ,ly:grob-array? "Objects to be spaced during page layout.")
;; ancient notation