+2004-07-23 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * lily/ledger-line-engraver.cc: new file.
+
+ * lily/ledger-line-spanner.cc (print): new file. Set limits to
+ ledger line length to avoid clashes.
+
+2004-07-22 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * Documentation/user/invoking.itexi (Invoking lilypond): remove
+ deprecated options
+
2004-07-21 Jan Nieuwenhuizen <janneke@gnu.org>
* SConstruct: Use only code files for TAGS. Change GO_FAST_BUTTON
2004-07-18 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ * VERSION: release 2.3.7
+
* stepmake/generic-vars.make (EXTRA_DIST_FILES): dist SConscript
files.
certain effect.
The controls available for tuning are described in a separate
-document, the @internalsref{Program reference} manual. This manual
+document, the @internalsref{Program reference} manual. That manual
lists all different variables, functions and options available in
LilyPond. It is written as a HTML document, which is available
@uref{http://lilypond.org/doc/Documentation/user/out-www/lilypond-internals/,on-line},
Print usage help.
@item -I,--include=@var{dir}
Add @var{dir} to LilyPond's include path.
-@item -m,--no-paper
- Produce MIDI output only.
-@item --no-lily
- Do not run @file{lilypond-bin}. Useful for debugging @code{lilypond}.
@item -o,--output=@var{file}
Generate output to @var{file}. The extension of @var{file} is ignored.
-@item --no-pdf
- Do not generate (PDF) or PS.
-
-@cindex PDF
-@cindex Scalable fonts
-
@item --png
Also generate pictures of each page, in PNG format.
@item --psgz
Gzip the postscript file.
-@item --html
- Make a .HTML file with links to all output files.
@item --preview
Also generate a picture of the first system of the score.
struct Drul_array
{
T array_[2];
- T &elem (Direction d)
- {
- assert (d==1 || d== -1);
- return array_[ (d+1)/2];
- }
- T &operator[] (Direction d)
+ T &elem_ref (Direction d)
{
- return elem (d);
+ assert (d==1 || d== -1);
+ return array_[ (d+1)/2];
}
T elem (Direction d) const
- {
+ {
assert (d==1 || d== -1);
return array_[ (d+1)/2];
- }
-
+ }
+ T &operator[] (Direction d)
+ {
+ return elem_ref (d);
+ }
T operator[] (Direction d) const
{
return elem (d);
}
Drul_array ()
- {
- }
+ {
+ }
Drul_array (T t1, T t2)
- {
- array_[0] = t1;
- array_[1] = t2;
- }
+ {
+ array_[0] = t1;
+ array_[1] = t2;
+ }
};
template<class T>
void
scale_drul (Drul_array<T> * dr, T x)
{
- dr->elem (LEFT) *= x;
- dr->elem (RIGHT) *= x;
+ dr->elem_ref (LEFT) *= x;
+ dr->elem_ref (RIGHT) *= x;
}
inline Real
}
void translate (T t)
{
- elem (LEFT) += t;
- elem (RIGHT) += t;
+ elem_ref (LEFT) += t;
+ elem_ref (RIGHT) += t;
}
void widen (T t)
{
- elem (LEFT) -= t;
- elem (RIGHT) += t;
+ elem_ref (LEFT) -= t;
+ elem_ref (RIGHT) += t;
}
/**
void intersect (Interval_t<T> h);
void add_point (T p)
{
- elem(LEFT) = elem (LEFT) <? p;
- elem(RIGHT) = elem (RIGHT) >? p;
+ elem_ref(LEFT) = elem (LEFT) <? p;
+ elem_ref(RIGHT) = elem (RIGHT) >? p;
}
T length () const;
T delta () const;
}
Interval_t<T> &operator += (T r) {
- elem (LEFT) += r;
- elem (RIGHT) +=r;
+ elem_ref (LEFT) += r;
+ elem_ref (RIGHT) +=r;
return *this;
}
Interval_t<T> &operator *= (T r) {
if (!is_empty ())
{
- elem (LEFT) *= r;
- elem (RIGHT) *= r;
+ elem_ref (LEFT) *= r;
+ elem_ref (RIGHT) *= r;
if (r < T (0))
swap();
{
T r = -elem (LEFT);
T l = -elem (RIGHT);
- elem (LEFT) = l;
- elem (RIGHT) =r;
+ elem_ref (LEFT) = l;
+ elem_ref (RIGHT) =r;
}
void swap ()
{
T t = elem (LEFT);
- elem (LEFT) = elem (RIGHT);
- elem (RIGHT) = t;
+ elem_ref (LEFT) = elem (RIGHT);
+ elem_ref (RIGHT) = t;
}
};
void
Interval_t<T>::set_empty ()
{
- elem (LEFT) = (T) infinity ();
- elem (RIGHT) = (T) -infinity ();
+ elem_ref (LEFT) = (T) infinity ();
+ elem_ref (RIGHT) = (T) -infinity ();
}
template<class T>
void
Interval_t<T>::set_full ()
{
- elem (LEFT) = (T) -infinity ();
- elem (RIGHT) = (T) infinity ();
+ elem_ref (LEFT) = (T) -infinity ();
+ elem_ref (RIGHT) = (T) infinity ();
}
template<class T>
void
Interval_t<T>::unite (Interval_t<T> h)
{
- elem (LEFT) = h.elem (LEFT) <? elem (LEFT);
- elem (RIGHT) = h.elem (RIGHT) >? elem (RIGHT);
+ elem_ref (LEFT) = h.elem (LEFT) <? elem (LEFT);
+ elem_ref (RIGHT) = h.elem (RIGHT) >? elem (RIGHT);
}
template<class T>
Interval_t<T>::intersect (Interval_t<T> h)
{
#if defined (__GNUG__) && !defined (__STRICT_ANSI__)
- elem (LEFT) = h.elem (LEFT) >? elem (LEFT);
- elem (RIGHT) = h.elem (RIGHT) <? elem (RIGHT);
+ elem_ref (LEFT) = h.elem (LEFT) >? elem (LEFT);
+ elem_ref (RIGHT) = h.elem (RIGHT) <? elem (RIGHT);
#else
- elem (LEFT) = max (h.elem (LEFT), elem (LEFT));
- elem (RIGHT) = min (h.elem (RIGHT), elem (RIGHT));
+ elem_ref (LEFT) = max (h.elem (LEFT), elem (LEFT));
+ elem_ref (RIGHT) = min (h.elem (RIGHT), elem (RIGHT));
#endif
}
--- /dev/null
+/*
+ ledger-line-engraver.cc -- implement Ledger_line_engraver=
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2004 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+*/
+
+
+#include "group-interface.hh"
+#include "spanner.hh"
+#include "engraver.hh"
+
+class Ledger_line_engraver : public Engraver
+{
+ Spanner * span_;
+
+public:
+ TRANSLATOR_DECLARATIONS (Ledger_line_engraver);
+
+protected:
+ virtual void finalize ();
+ virtual void process_music ();
+ virtual void acknowledge_grob (Grob_info);
+};
+
+Ledger_line_engraver::Ledger_line_engraver()
+{
+ span_ = 0;
+}
+
+void
+Ledger_line_engraver::process_music ()
+{
+ if (!span_)
+ {
+ span_ = make_spanner("LedgerLineSpanner", SCM_EOL);
+
+ span_->set_bound (LEFT, unsmob_grob (get_property ("currentCommandColumn")));
+ }
+}
+
+void
+Ledger_line_engraver::finalize ()
+{
+ if (span_)
+ span_->set_bound (RIGHT,unsmob_grob (get_property ("currentCommandColumn")));
+}
+
+
+void
+Ledger_line_engraver::acknowledge_grob (Grob_info s)
+{
+ Pointer_group_interface::add_grob (span_, ly_symbol2scm ("note-heads"),
+ s.grob_);
+}
+
+ENTER_DESCRIPTION (Ledger_line_engraver,
+ "Creates spanner to draw ledger lines",
+ /* creats*/ "LedgerLineSpanner",
+ /* accepts */ "",
+ /* acks */ "note-head-interface", // ledgered-interface?
+ /* reads */ "",
+ /* write */ "")
--- /dev/null
+/*
+ ledger-line-spanner.cc -- implement Ledger_line_spanner
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2004 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+*/
+
+#include <map>
+
+#include "item.hh"
+#include "note-head.hh"
+#include "staff-symbol-referencer.hh"
+#include "staff-symbol.hh"
+#include "lookup.hh"
+#include "spanner.hh"
+#include "group-interface.hh"
+#include "paper-column.hh"
+
+struct Ledger_line_spanner
+{
+ DECLARE_SCHEME_CALLBACK (print, (SCM ));
+ static Stencil brew_ledger_lines (Grob *me,
+ int pos,
+ int interspaces,
+ Interval x_extent,
+ Real left_shorten);
+
+ static bool has_interface (Grob*);
+};
+
+
+Stencil
+Ledger_line_spanner::brew_ledger_lines (Grob *me,
+ int pos,
+ int interspaces,
+ Interval x_extent,
+ Real left_shorten)
+{
+ Grob *staff = Staff_symbol_referencer::get_staff_symbol (me);
+ Real inter_f = Staff_symbol_referencer::staff_space (me)/2;
+ int line_count = ((abs (pos) < interspaces)
+ ? 0
+ : (abs (pos) - interspaces) / 2);
+ Stencil stencil;
+ if (line_count)
+ {
+ Real ledgerlinethickness =
+ Staff_symbol::get_ledger_line_thickness (staff);
+ Real blotdiameter = ledgerlinethickness;
+ Interval y_extent =
+ Interval (-0.5*(ledgerlinethickness),
+ +0.5*(ledgerlinethickness));
+ Stencil proto_ledger_line =
+ Lookup::round_filled_box (Box (x_extent, y_extent), blotdiameter);
+
+ x_extent[LEFT] += left_shorten;
+ Stencil proto_first_line =
+ Lookup::round_filled_box (Box (x_extent, y_extent), blotdiameter);
+
+ Direction dir = (Direction)sign (pos);
+ Real offs = (Staff_symbol_referencer::on_staffline (me, pos))
+ ? 0.0
+ : -dir * inter_f;
+
+
+ offs += pos * inter_f;
+ for (int i = 0; i < line_count; i++)
+ {
+ Stencil ledger_line ((i == 0)
+ ? proto_first_line
+ : proto_ledger_line
+ );
+ ledger_line.translate_axis (-dir * inter_f * i * 2 + offs, Y_AXIS);
+ stencil.add_stencil (ledger_line);
+ }
+ }
+
+ return stencil;
+}
+
+
+struct Ledger_request
+{
+ Interval ledger_extent_;
+ Interval head_extent_;
+ int position_;
+ bool excentric_;
+ Ledger_request () {
+ ledger_extent_.set_empty ();
+ head_extent_.set_empty ();
+ position_ = 0;
+ }
+};
+
+typedef std::map<int, Drul_array<Ledger_request> > Ledger_requests;
+
+
+/*
+ TODO: ledger share a lot of info. Lots of room to optimize away common
+ use of objects/variables.
+ */
+MAKE_SCHEME_CALLBACK (Ledger_line_spanner,print,1);
+SCM
+Ledger_line_spanner::print (SCM smob)
+{
+ Spanner *me = dynamic_cast<Spanner*> (unsmob_grob (smob));
+ Link_array<Grob> heads (Pointer_group_interface__extract_grobs (me, (Grob*)0, "note-heads"));
+
+ Stencil ledgers;
+ Stencil default_ledger;
+
+ Grob * common[NO_AXES];
+ for (int i = X_AXIS; i < NO_AXES; i++)
+ common[Axis (i)] = common_refpoint_of_array (heads, me, Axis(i));
+
+ int interspaces = Staff_symbol_referencer::line_count (me)-1;
+ Ledger_requests reqs;
+ Real length_fraction = 0.25 * 2;
+ for (int i = heads.size (); i--; )
+ {
+ Item *h = dynamic_cast<Item*> (heads[i]);
+
+ int pos = Staff_symbol_referencer::get_rounded_position (h);
+ if (abs (pos) > interspaces + 1)
+ {
+ Interval head_extent = h->extent (common[X_AXIS], X_AXIS);
+ Interval ledger_extent = Interval (head_extent.linear_combination (-1 - length_fraction),
+ head_extent.linear_combination (1 + length_fraction));
+
+ Direction vdir = Direction (sign (pos));
+ int rank = Paper_column::get_rank (h->get_column ());
+
+ reqs[rank][vdir].ledger_extent_.unite (ledger_extent);
+ reqs[rank][vdir].head_extent_.unite (head_extent);
+ reqs[rank][vdir].position_ =
+ vdir * ((vdir* reqs[rank][vdir].position_) >? (vdir *pos));
+ }
+ }
+
+ Real gap = robust_scm2double (me->get_property ("gap"), 0.15);
+ Ledger_requests::iterator last (reqs.end ());
+ for (Ledger_requests::iterator i (reqs.begin ());
+ i != reqs.end (); last = i++)
+ {
+ if (last == reqs.end ())
+ {
+ continue;
+ }
+
+ Direction d = DOWN;
+ do
+ {
+ if (abs (last->second[d].position_) > interspaces + 1
+ && abs (i->second[d].position_) > interspaces + 1)
+ {
+ Real center =
+ (last->second[d].head_extent_[RIGHT]
+ + i->second[d].head_extent_[LEFT] )/2;
+
+ Direction which = LEFT;
+ do
+ {
+ Ledger_request &lr = ((which == LEFT) ? *last : *i).second[d];
+
+
+ // due tilt of quarter note-heads
+ Real excentricity = 0; //.1;
+ Real limit = (center + which * gap/2 + excentricity);
+ lr.ledger_extent_.elem_ref (-which)
+ = which * (which * lr.ledger_extent_[-which] >? which * limit);
+ }
+ while (flip (&which) != LEFT);
+ }
+ }
+ while (flip (&d) != DOWN);
+ }
+
+ for (Ledger_requests::const_iterator i (reqs.begin ());
+ i != reqs.end (); i++)
+ {
+ Direction d = DOWN;
+ do
+ {
+ Ledger_request lr = (*i).second[d];
+ ledgers.add_stencil (brew_ledger_lines (me,
+ lr.position_,
+ interspaces,
+ lr.ledger_extent_,
+ 0.0));
+ }
+ while (flip (&d) != DOWN);
+ }
+
+ ledgers.translate_axis (-me->relative_coordinate (common[X_AXIS], X_AXIS),
+ X_AXIS);
+
+ return ledgers.smobbed_copy ();
+}
+
+ADD_INTERFACE (Ledger_line_spanner,
+ "ledger-line-interface",
+ "This spanner draws the ledger lines of a staff on note heads. ",
+ "note-heads thickness gap length minimum-length")
return log (x) /log (2.0);
}
+
me->warning (_f ("note head `%s' not found", font_char.to_str0 ()));
}
+#if 0
int interspaces = Staff_symbol_referencer::line_count (me)-1;
int pos = Staff_symbol_referencer::get_rounded_position (me);
if (with_ledgers && interspaces >= 0
left_shorten,
false));
}
+#endif
+
return out;
}
\consists "Breathing_sign_engraver"
% \consists "Rest_engraver"
\consists "Note_heads_engraver"
+ \consists "Ledger_line_engraver"
\consists "Rest_engraver"
\consists "Stem_engraver"
(breakable . #t)
(meta . ((interfaces . (key-signature-interface font-interface break-aligned-interface item-interface ))))
))
-
+ (LedgerLineSpanner
+ . (
+ (print-function . ,Ledger_line_spanner::print)
+ (meta . ((interfaces . (spanner-interface ledger-line-interface))))
+ ))
+
(LigatureBracket
. (
(ligature-primitive-callback . ,Note_head::print)