source file of the GNU LilyPond music typesetter
- (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ (c) 1997--2008 Han-Wen Nienhuys <hanwen@xs4all.nl>
*/
#include "grob.hh"
#include "ly-smobs.icc"
Grob *
-Grob::clone (int count) const
+Grob::clone () const
{
- return new Grob (*this, count);
+ return new Grob (*this);
}
-Grob::Grob (SCM basicprops,
- Object_key const *key)
+Grob::Grob (SCM basicprops)
{
- key_ = key;
/* FIXME: default should be no callback. */
self_scm_ = SCM_EOL;
GC. After smobify_self (), they are. */
smobify_self ();
- /*
- We always get a new key object for a new grob.
- */
- if (key_)
- ((Object_key *)key_)->unprotect ();
-
SCM meta = get_property ("meta");
if (scm_is_pair (meta))
- interfaces_ = scm_cdr (scm_assq (ly_symbol2scm ("interfaces"), meta));
+ {
+ interfaces_ = scm_cdr (scm_assq (ly_symbol2scm ("interfaces"), meta));
+
+ SCM object_cbs = scm_assq (ly_symbol2scm ("object-callbacks"), meta);
+ if (scm_is_pair (object_cbs))
+ {
+ for (SCM s = scm_cdr (object_cbs); scm_is_pair (s); s = scm_cdr (s))
+ set_object (scm_caar (s), scm_cdar (s));
+ }
+ }
if (get_property_data ("X-extent") == SCM_EOL)
set_property ("X-extent", Grob::stencil_width_proc);
set_property ("Y-extent", Grob::stencil_height_proc);
}
-Grob::Grob (Grob const &s, int copy_index)
+Grob::Grob (Grob const &s)
: dim_cache_ (s.dim_cache_)
{
- key_ = (use_object_keys) ? new Copied_key (s.key_, copy_index) : 0;
original_ = (Grob *) & s;
self_scm_ = SCM_EOL;
layout_ = 0;
smobify_self ();
- if (key_)
- ((Object_key *)key_)->unprotect ();
}
Grob::~Grob ()
Real x = scm_to_double (scm_cadr (rot));
Real y = scm_to_double (scm_caddr (rot));
- retval.rotate (angle, Offset (x, y));
+ retval.rotate_degrees (angle, Offset (x, y));
}
/* color support... see interpret_stencil_expression () for more... */
Real
Grob::relative_coordinate (Grob const *refp, Axis a) const
{
- if (refp == this)
+ /* eaa - hmmm, should we do a programming_error() here? */
+ if ((this == NULL) || (refp == this))
return 0.0;
/* We catch PARENT_L_ == nil case with this, but we crash if we did
Real off = 0;
if (dim_cache_[Y_AXIS].offset_)
- off = *dim_cache_[Y_AXIS].offset_;
+ {
+ if (to_boolean (get_property ("pure-Y-offset-in-progress")))
+ programming_error ("cyclic chain in pure-Y-offset callbacks");
+
+ off = *dim_cache_[Y_AXIS].offset_;
+ }
else
{
SCM proc = get_property_data ("Y-offset");
dim_cache_[Y_AXIS].offset_ = new Real (0.0);
+ set_property ("pure-Y-offset-in-progress", SCM_BOOL_T);
off = robust_scm2double (call_pure_function (proc,
scm_list_1 (self_scm ()),
start, end),
0.0);
+ del_property ("pure-Y-offset-in-progress");
delete dim_cache_[Y_AXIS].offset_;
dim_cache_[Y_AXIS].offset_ = 0;
}
(a == X_AXIS)
? ly_symbol2scm ("X-extent")
: ly_symbol2scm ("Y-extent");
-
+
SCM ext = internal_get_property (ext_sym);
if (is_number_pair (ext))
real_ext.unite (ly_scm2interval (ext));
Interval
Grob::pure_height (Grob *refp, int start, int end)
{
- SCM proc = get_property_data ( ly_symbol2scm ("Y-extent"));
- Interval iv = robust_scm2interval (call_pure_function (proc,
- scm_list_1 (self_scm ()),
- start, end),
- Interval (0, 0));
+ SCM proc = get_property_data (ly_symbol2scm ("Y-extent"));
+ SCM iv_scm = call_pure_function (proc,
+ scm_list_1 (self_scm ()),
+ start, end);
+ Interval iv = robust_scm2interval (iv_scm, Interval (0, 0));
Real offset = pure_relative_y_coordinate (refp, start, end);
SCM min_ext = get_property ("minimum-Y-extent");
if (!iv.is_empty () && is_number_pair (min_ext))
iv.unite (ly_scm2interval (min_ext));
- iv.translate (offset);
+ if (!iv.is_empty ())
+ iv.translate (offset);
return iv;
}
}
Interval_t<int>
-Grob::spanned_rank_iv ()
+Grob::spanned_rank_interval () const
{
return Interval_t<int> (-1, 0);
}
ADD_INTERFACE (Grob,
- "A grob represents a piece of music notation\n"
+ "A grob represents a piece of music notation.\n"
"\n"
- "All grobs have an X and Y-position on the page. These X and Y positions\n"
- "are stored in a relative format, so they can easily be combined by\n"
- "stacking them, hanging one grob to the side of another, and coupling\n"
- "them into a grouping objects.\n"
+ "All grobs have an X and Y@tie{}position on the page. These"
+ " X and Y@tie{}positions are stored in a relative format, thus"
+ " they can easily be combined by stacking them, hanging one"
+ " grob to the side of another, or coupling them into grouping"
+ " objects.\n"
"\n"
- "Each grob has a reference point (a.k.a. parent): the position of a grob\n"
- "is stored relative to that reference point. For example the X-reference\n"
- "point of a staccato dot usually is the note head that it applies\n"
- "to. When the note head is moved, the staccato dot moves along\n"
- "automatically.\n"
+ "Each grob has a reference point (a.k.a.@: parent): The"
+ " position of a grob is stored relative to that reference"
+ " point. For example, the X@tie{}reference point of a staccato"
+ " dot usually is the note head that it applies to. When the"
+ " note head is moved, the staccato dot moves along"
+ " automatically.\n"
"\n"
- "A grob is often associated with a symbol, but some grobs do not print\n"
- "any symbols. They take care of grouping objects. For example, there is a\n"
- "separate grob that stacks staves vertically. The @ref{NoteCollision}\n"
- "is also an abstract grob: it only moves around chords, but doesn't print\n"
- "anything.\n"
+ "A grob is often associated with a symbol, but some grobs do"
+ " not print any symbols. They take care of grouping objects."
+ " For example, there is a separate grob that stacks staves"
+ " vertically. The @ref{NoteCollision} object is also an"
+ " abstract grob: It only moves around chords, but doesn't print"
+ " anything.\n"
"\n"
- "Grobs have a properties: Scheme variables, that can be read and set. "
- "They have two types. Immutable variables "
- "define the default style and behavior. They are shared between many objects. "
- "They can be changed using @code{\\override} and @code{\\revert}. "
- "\n\n"
- "Mutable properties are variables that are specific to one grob. Typically, "
- "lists of other objects, or results from computations are stored in"
- "mutable properties: every call to set-grob-property (or its C++ equivalent) "
- "sets a mutable property. "
- "\n\n"
- "The properties @code{after-line-breaking} and @code{before-line-breaking} "
- "are dummies that are not user-serviceable. "
-
- ,
+ "Grobs have properties (Scheme variables) that can be read and"
+ " set. Two types of them exist: immutable and mutable."
+ " Immutable variables define the default style and behavior."
+ " They are shared between many objects. They can be changed"
+ " using @code{\\override} and @code{\\revert}. Mutable"
+ " properties are variables that are specific to one grob."
+ " Typically, lists of other objects, or results from"
+ " computations are stored in mutable properties. In"
+ " particular, every call to @code{set-grob-property} (or its"
+ " C++ equivalent) sets a mutable property.\n"
+ "\n"
+ "The properties @code{after-line-breaking} and"
+ " @code{before-line-breaking} are dummies that are not"
+ " user-serviceable.",
/* properties */
"X-extent "
"before-line-breaking "
"cause "
"color "
+ "cross-staff "
"extra-X-extent "
"extra-Y-extent "
"extra-offset "
"outside-staff-horizontal-padding "
"outside-staff-padding "
"outside-staff-priority "
+ "pure-Y-offset-in-progress "
"rotation "
"springs-and-rods "
"staff-symbol "
"transparent "
);
-
-
-
-
/****************************************************************
CALLBACKS
****************************************************************/
-
static SCM
grob_stencil_extent (Grob *me, Axis a)
{
return grob_stencil_extent (me, Y_AXIS);
}
-MAKE_SCHEME_CALLBACK(Grob, y_parent_positioning, 1);
+MAKE_SCHEME_CALLBACK (Grob, y_parent_positioning, 1);
SCM
Grob::y_parent_positioning (SCM smob)
{
}
-MAKE_SCHEME_CALLBACK(Grob, x_parent_positioning, 1);
+MAKE_SCHEME_CALLBACK (Grob, x_parent_positioning, 1);
SCM
Grob::x_parent_positioning (SCM smob)
{
Grob *
common_refpoint_of_array (vector<Grob*> const &arr, Grob *common, Axis a)
{
- for (vsize i = arr.size (); i--;)
- if (Grob *s = arr[i])
- {
- if (common)
- common = common->common_refpoint (s, a);
- else
- common = s;
- }
+ for (vsize i = 0; i < arr.size (); i++)
+ if (common)
+ common = common->common_refpoint (arr[i], a);
+ else
+ common = arr[i];
return common;
}