--- /dev/null
+/*
+ ligature-bracket-engraver.cc -- implement Ligature__bracket_engraver
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2002 Juergen Reuter <reuter@ipd.uka.de>
+
+ */
+#include "engraver.hh"
+#include "musical-request.hh"
+#include "warn.hh"
+#include "drul-array.hh"
+#include "item.hh"
+#include "spanner.hh"
+#include "score-engraver.hh"
+#include "note-head.hh"
+#include "stem.hh"
+#include "rest.hh"
+
+class Ligature_bracket_engraver : public Engraver
+{
+ Drul_array<Span_req*> reqs_drul_;
+
+ Spanner *finished_ligature_bracket_p_;
+ Spanner *ligature_bracket_p_;
+ Span_req *prev_start_req_;
+
+ // moment where ligature started.
+ Moment ligature_start_mom_;
+ Grob *last_bound;
+
+protected:
+ virtual void stop_translation_timestep ();
+ virtual void start_translation_timestep ();
+ virtual void finalize ();
+
+ virtual void acknowledge_grob (Grob_info);
+ virtual bool try_music (Music*);
+ virtual void process_music ();
+
+public:
+ TRANSLATOR_DECLARATIONS(Ligature_bracket_engraver);
+
+private:
+ void typeset_ligature_bracket ();
+};
+
+
+Ligature_bracket_engraver::Ligature_bracket_engraver ()
+{
+ ligature_bracket_p_ = 0;
+ finished_ligature_bracket_p_ = 0;
+ reqs_drul_[LEFT] = reqs_drul_[RIGHT] = 0;
+ prev_start_req_ = 0;
+ last_bound = 0;
+}
+
+bool
+Ligature_bracket_engraver::try_music (Music *m)
+{
+ if (Span_req *req_ = dynamic_cast<Span_req*> (m))
+ {
+ if (scm_equal_p (req_->get_mus_property ("span-type"),
+ ly_str02scm ("abort")) == SCM_BOOL_T)
+ {
+ reqs_drul_[START] = 0;
+ reqs_drul_[STOP] = 0;
+ if (ligature_bracket_p_)
+ ligature_bracket_p_->suicide ();
+ ligature_bracket_p_ = 0;
+ }
+ else if (scm_equal_p (req_->get_mus_property ("span-type"),
+ ly_str02scm ("ligature-bracket")) == SCM_BOOL_T)
+ {
+ Direction d = req_->get_span_dir ();
+ reqs_drul_[d] = req_;
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+Ligature_bracket_engraver::process_music ()
+{
+ if (reqs_drul_[STOP])
+ {
+ if (!ligature_bracket_p_)
+ reqs_drul_[STOP]->origin ()->warning (_ ("can't find start of ligature"));
+ else
+ {
+ if (!last_bound)
+ {
+ reqs_drul_[STOP]->origin ()->warning (_ ("no right bound"));
+ }
+ else
+ {
+ ligature_bracket_p_->set_bound (RIGHT, last_bound);
+ }
+ }
+ prev_start_req_ = 0;
+ finished_ligature_bracket_p_ = ligature_bracket_p_;
+ ligature_bracket_p_ = 0;
+ }
+ last_bound = unsmob_grob (get_property ("currentMusicalColumn"));
+
+ if (ligature_bracket_p_)
+ {
+ // TODO: maybe forbid breaks only if not transcribing
+ top_engraver ()->forbid_breaks ();
+ }
+ if (reqs_drul_[START])
+ {
+ if (ligature_bracket_p_)
+ {
+ reqs_drul_[START]->origin ()->warning (_ ("already have a ligature"));
+ return;
+ }
+
+ prev_start_req_ = reqs_drul_[START];
+ ligature_bracket_p_ = new Spanner (get_property ("LigatureBracket"));
+
+ Grob *bound = unsmob_grob (get_property ("currentMusicalColumn"));
+ if (!bound)
+ {
+ reqs_drul_[START]->origin ()->warning (_ ("no left bound"));
+ }
+ else
+ {
+ ligature_bracket_p_->set_bound (LEFT, bound);
+ }
+
+ ligature_start_mom_ = now_mom ();
+
+ announce_grob(ligature_bracket_p_, reqs_drul_[START]->self_scm());
+ }
+}
+
+void
+Ligature_bracket_engraver::start_translation_timestep ()
+{
+ reqs_drul_[START] = 0;
+ reqs_drul_[STOP] = 0;
+}
+
+void
+Ligature_bracket_engraver::typeset_ligature_bracket ()
+{
+ if (finished_ligature_bracket_p_)
+ {
+ typeset_grob (finished_ligature_bracket_p_);
+ finished_ligature_bracket_p_ = 0;
+ }
+}
+
+void
+Ligature_bracket_engraver::stop_translation_timestep ()
+{
+ typeset_ligature_bracket ();
+}
+
+void
+Ligature_bracket_engraver::finalize ()
+{
+ typeset_ligature_bracket ();
+ if (ligature_bracket_p_)
+ {
+ prev_start_req_->origin ()->warning (_ ("unterminated ligature"));
+ ligature_bracket_p_->suicide ();
+ }
+}
+
+void
+Ligature_bracket_engraver::acknowledge_grob (Grob_info info)
+{
+ if (ligature_bracket_p_)
+ {
+ if (Rest::has_interface (info.grob_l_))
+ {
+ reqs_drul_[START]->origin ()->warning (_ ("ligature may not contain rest; ignoring rest"));
+ prev_start_req_->origin ()->warning (_ ("ligature was started here"));
+ // TODO: maybe better should stop ligature here rather than
+ // ignoring the rest?
+ }
+ }
+}
+
+ENTER_DESCRIPTION(Ligature_bracket_engraver,
+/* descr */ "Handles Ligature_requests by engraving Ligature brackets.",
+/* creats*/ "LigatureBracket",
+/* acks */ "rest-interface",
+/* reads */ "",
+/* write */ "");
--- /dev/null
+/*
+ ligature-bracket.cc -- implement Ligature_bracket
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2002 Juergen Reuter <reuter@ipd.uka.de>
+*/
+
+#include "ligature-bracket.hh"
+#include "item.hh"
+#include "paper-def.hh"
+#include "spanner.hh"
+#include "staff-symbol-referencer.hh"
+#include "lookup.hh"
+#include "box.hh"
+
+static Molecule
+brew_edge (Direction dir, Real thickness, Real width, Real height,
+ Real blotdiameter)
+{
+ Molecule hline = Lookup::roundfilledbox (Box (Interval (0, width),
+ Interval (0, thickness)),
+ blotdiameter);
+ hline.translate_axis (height - thickness, Y_AXIS);
+
+ Molecule vline = Lookup::roundfilledbox (Box (Interval (0, thickness),
+ Interval (0, height)),
+ blotdiameter);
+ if (dir == RIGHT)
+ {
+ vline.translate_axis (width - thickness, X_AXIS);
+ }
+
+ Molecule edge = Molecule ();
+ edge.add_molecule (hline);
+ edge.add_molecule (vline);
+ return edge;
+}
+
+MAKE_SCHEME_CALLBACK (Ligature_bracket, brew_molecule, 1);
+SCM
+Ligature_bracket::brew_molecule (SCM smob)
+{
+ Grob *me = unsmob_grob (smob);
+ Spanner *spanner = dynamic_cast<Spanner*> (me);
+ Real blotdiameter = me->paper_l ()->get_var ("blotdiameter");
+ Real staff_space = Staff_symbol_referencer::staff_space (me);
+
+ Real thickness = me->paper_l ()->get_var ("linethickness");
+ SCM grob_thickness = me->get_grob_property ("thickness");
+ if (gh_number_p (grob_thickness))
+ thickness *= gh_scm2double (grob_thickness);
+
+ SCM edge_width_scm = me->get_grob_property ("width");
+ Real edge_width;
+ if (gh_number_p (edge_width_scm))
+ {
+ edge_width = gh_scm2double (edge_width_scm);
+ }
+ else
+ {
+ edge_width = 0.75;
+ }
+ edge_width *= staff_space;
+
+ SCM edge_height_scm = me->get_grob_property ("height");
+ Real edge_height;
+ if (gh_number_p (edge_height_scm))
+ {
+ edge_height = gh_scm2double (edge_height_scm);
+ }
+ else
+ {
+ edge_height = 0.5;
+ }
+ edge_height *= staff_space;
+
+ Item* left_bound = spanner->get_bound (LEFT);
+ Item* right_bound = spanner->get_bound (RIGHT);
+
+ Molecule bracket = Molecule ();
+
+ Real y_min_offs =
+ 0.5 * Staff_symbol_referencer::line_count (me) * staff_space;
+ Real y_left_offs = y_min_offs;
+ Real y_right_offs = y_min_offs;
+
+ Real left_bound_left_extent = 0;
+
+ if (left_bound)
+ {
+ Molecule left_edge =
+ brew_edge (LEFT, thickness, edge_width, edge_height, blotdiameter);
+ Grob *left_common_x = me->common_refpoint (left_bound, X_AXIS);
+ left_bound_left_extent =
+ left_bound->extent (left_common_x, X_AXIS)[LEFT];
+ left_edge.translate_axis (left_bound_left_extent, X_AXIS);
+ bracket.add_molecule (left_edge);
+ Grob *left_common_y = me->common_refpoint (left_bound, Y_AXIS);
+ y_left_offs =
+ max(y_left_offs, left_bound->extent (left_common_y, Y_AXIS)[UP]);
+ }
+ else
+ {
+ me->warning (_ ("no left bound"));
+ }
+
+ if (right_bound)
+ {
+ Molecule right_edge =
+ brew_edge (RIGHT, thickness, edge_width, edge_height, blotdiameter);
+ Grob *staff_symbol = Staff_symbol_referencer::staff_symbol_l (me);
+ Grob *right_common_bound_x =
+ right_bound->common_refpoint (staff_symbol, X_AXIS);
+
+ Real left_offs = 0;
+ if (left_bound)
+ {
+ Grob *left_common_bound_x =
+ left_bound->common_refpoint (staff_symbol, X_AXIS);
+ left_offs = left_bound->extent (left_common_bound_x, X_AXIS)[LEFT];
+ }
+
+ Real right_offs =
+ right_bound->extent (right_common_bound_x, X_AXIS)[RIGHT];
+
+ right_edge.translate_axis (+ right_offs
+ - left_offs
+ + left_bound_left_extent
+ - edge_width,
+ X_AXIS);
+ bracket.add_molecule (right_edge);
+ Grob *right_common_y = me->common_refpoint (right_bound, Y_AXIS);
+ y_right_offs =
+ max(y_right_offs, right_bound->extent (right_common_y, Y_AXIS)[UP]);
+ }
+ else
+ {
+ me->warning (_ ("no left bound"));
+ }
+
+ bracket.translate_axis (max (y_left_offs, y_right_offs), Y_AXIS);
+
+ return bracket.smobbed_copy ();
+}