/*
- item.cc -- implement Item
+ This file is part of LilyPond, the GNU music typesetter.
- source file of the GNU LilyPond music typesetter
+ Copyright (C) 1997--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
- (c) 1997--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ LilyPond is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ LilyPond is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
*/
#include "item.hh"
#include "moment.hh"
-
Grob *
Item::clone () const
{
: Grob (s)
{
broken_to_drul_[LEFT] = broken_to_drul_[RIGHT] = 0;
+ cached_pure_height_valid_ = false;
}
/**
- Item copy ctor. Copy nothing: everything should be a elt property
+ Item copy ctor. Copy nothing: everything should be an elt property
or a special purpose pointer (such as broken_to_drul_[]) */
Item::Item (Item const &s)
: Grob (s)
{
broken_to_drul_[LEFT] = broken_to_drul_[RIGHT] = 0;
+ cached_pure_height_valid_ = false;
}
bool
Item::is_non_musical (Grob *me)
{
- if (me->original ())
- return false;
-
Item *i = dynamic_cast<Item *> (me->get_parent (X_AXIS));
return i ? Item::is_non_musical (i) : to_boolean (me->get_property ("non-musical"));
}
Item::copy_breakable_items ()
{
Drul_array<Item *> new_copies;
- Direction i = LEFT;
- do
+ for (LEFT_and_RIGHT (d))
{
Grob *dolly = clone ();
Item *item = dynamic_cast<Item *> (dolly);
get_root_system (this)->typeset_grob (item);
- new_copies[i] = item;
+ new_copies[d] = item;
}
- while (flip (&i) != LEFT);
broken_to_drul_ = new_copies;
}
void
Item::discretionary_processing ()
{
- if (is_broken ())
+ if (is_broken () || original ())
return;
if (Item::is_non_musical (this))
if (get_system () == l)
return (Item *) (this);
- Direction d = LEFT;
- do
+ for (LEFT_and_RIGHT (d))
{
Grob *s = broken_to_drul_[d];
if (s && s->get_system () == l)
- return s;
+ return s;
}
- while (flip (&d) != LEFT);
return 0;
}
bool
Item::break_visible (Grob *g)
{
- Item *it = dynamic_cast<Item*> (g);
+ Item *it = dynamic_cast<Item *> (g);
SCM vis = g->get_property ("break-visibility");
if (scm_is_vector (vis))
return to_boolean (scm_c_vector_ref (vis, it->break_status_dir () + 1));
int pos = 1;
int pc_rank = Paper_column::get_rank (get_column ());
if (pc_rank == start)
- pos = 2;
+ pos = 2;
else if (pc_rank == end)
- pos = 0;
+ pos = 0;
return to_boolean (scm_vector_ref (vis, scm_from_int (pos)));
}
return true;
}
Interval_t<Moment>
-spanned_time_interval (Item *l, Item *r)
+spanned_time_interval (Item *l, Item *r)
{
- Drul_array<Item*> bounds (l, r);
+ Drul_array<Item *> bounds (l, r);
Interval_t<Moment> iv;
- Direction d = LEFT;
- do
+ for (LEFT_and_RIGHT (d))
{
if (bounds[d] && bounds[d]->get_column ())
- iv[d] = robust_scm2moment (bounds[d]->get_column ()->get_property ("when"),
- iv[d]);
+ iv[d] = robust_scm2moment (bounds[d]->get_column ()->get_property ("when"),
+ iv[d]);
}
- while (flip (&d) != LEFT);
- do
+ for (LEFT_and_RIGHT (d))
{
if (!bounds[d] || !bounds[d]->get_column ())
- iv[d] = iv[-d];
+ iv[d] = iv[-d];
}
- while (flip (&d) != LEFT);
-
-
+
return iv;
}
-
void
Item::derived_mark () const
{
scm_gc_mark (broken_to_drul_[RIGHT]->self_scm ());
}
-Item *
-unsmob_item (SCM s)
+Interval
+Item::pure_y_extent (Grob *g, int start, int end)
{
- return dynamic_cast<Item *> (unsmob_grob (s));
+ if (cached_pure_height_valid_)
+ return cached_pure_height_ + pure_relative_y_coordinate (g, start, end);
+ /* Note: cached_pure_height_ does not notice if start changes, implicitly
+ assuming that Items' pure_heights do not depend on 'start' or 'end'.
+ */
+
+ cache_pure_height (Grob::pure_y_extent (this, start, end));
+ return cached_pure_height_ + pure_relative_y_coordinate (g, start, end);
}
-ADD_INTERFACE (Item,
+void
+Item::cache_pure_height (Interval height)
+{
+ cached_pure_height_ = height;
+ cached_pure_height_valid_ = true;
+}
- "Grobs can be distinguished in their role in the horizontal spacing.\n"
- "Many grobs define constraints on the spacing by their sizes. For\n"
- "example, note heads, clefs, stems, and all other symbols with a fixed\n"
- "shape. These grobs form a subtype called @code{Item}.\n"
- "\n"
- "\n"
- "Some items need special treatment for line breaking. For example, a\n"
- "clef is normally only printed at the start of a line (i.e. after a\n"
- "line break). To model this, `breakable' items (clef, key signature,\n"
- "bar lines, etc.) are copied twice. Then we have three versions of each\n"
- "breakable item: one version if there is no line break, one version\n"
- "that is printed before the line break (at the end of a system), one\n"
- "version that is printed after the line break.\n"
- "\n"
- "Whether these versions are visible and take up space, is determined by\n"
- "the outcome of the @code{break-visibility}. This grob property is a\n"
- "function taking a direction (-1, 0 or 1) as argument. It returns a\n"
- "cons of booleans, signifying whether this grob should be transparent\n"
- "and have no extent.\n"
- "\n"
- "The following variables for break-visibility are predefined:\n"
- "@example\n"
- " grob will show: before no after\n"
- " break break break\n"
- " all-invisible no no no\n"
- " begin-of-line-visible no no yes\n"
- " end-of-line-visible yes no no\n"
- " all-visible yes yes yes\n"
- " begin-of-line-invisible yes yes no\n"
- " end-of-line-invisible no yes yes\n"
- " center-invisible yes no yes\n"
- "@end example\n",
-
- /* properties */
- "break-visibility "
- "extra-spacing-width "
- "infinite-spacing-height "
- "non-musical")
+ADD_INTERFACE (Item,
+ "Grobs can be distinguished in their role in the horizontal"
+ " spacing. Many 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}.\n"
+ "\n"
+ "Some items need special treatment for line breaking. For"
+ " example, a clef is normally only printed at the start of a"
+ " line (i.e., after a line break). To model this,"
+ " @q{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), and one version that is printed after the line"
+ " break.\n"
+ "\n"
+ "Whether these versions are visible and take up space is"
+ " determined by the outcome of the @code{break-visibility}"
+ " grob property, which is a function taking a direction"
+ " (@w{@code{-1}}, @code{0} or@tie{}@code{1}) as an argument. It"
+ " returns a cons of booleans, signifying whether this grob"
+ " should be transparent and have no extent.\n"
+ "\n"
+ "The following variables for @code{break-visibility} are"
+ " predefined:\n"
+ "@example\n"
+ " grob will show: before no after\n"
+ " break break break\n"
+ " all-invisible no no no\n"
+ " begin-of-line-visible no no yes\n"
+ " end-of-line-visible yes no no\n"
+ " all-visible yes yes yes\n"
+ " begin-of-line-invisible yes yes no\n"
+ " end-of-line-invisible no yes yes\n"
+ " center-invisible yes no yes\n"
+ "@end example",
+
+ /* properties */
+ "break-visibility "
+ "extra-spacing-height "
+ "extra-spacing-width "
+ "non-musical "
+ );