* moment of the second note. Actually, it should take the moment of
* the first note.
*
- * TODO: Introduce "\~" as alternative syntax for "\porrectus"?
+ * FIXME: Turn off typesetting of stems, flags, dots, etc.
*
* TODO: Hufnagel support.
*
- * TODO: Fine-tuning of porrectus shape. In particular, the mensural
- * non-solid shape could either be slightly bigger in height, or the
- * extrem points could be slightly vertically shifted apart.
+ * TODO: Fine-tuning of vaticana-style porrectus shape; in particular,
+ * ensure solidity if solid is set to #t and thickness is very small.
*
* TODO: For white mensural (i.e. #'style=#'mensural, #'solid=##f)
* porrectus grobs, it is possible to automatically determine all
* porrectus specific properties (add-stem, stem-direction) solely
* from the duration of the contributing notes and time-signature.
* Introduce a boolean grob property called auto-config, so that, if
- * turned on, lily automatically sets the remaining properties
- * properly.
+ * turned on, lily automatically sets the properties add-stem and
+ * stem-direction properly.
*
- * TODO: The following issues are not (and should not be) handled by
- * this engraver: (1) accidentals placement, (2) avoiding line
- * breaking inbetween porrectus, (3) spacing. For example, currently
- * only the accidental for the second note (cp. the above FIXME) is
- * printed. These issues should be resolved by some sort of ligature
- * context that encloses use of this engraver, using syntax like:
- * \ligature { e \porrectus c }.
+ * TODO: The following issues are currently not handled by this
+ * engraver: (1) accidentals placement, (2) avoiding line breaking
+ * inbetween porrectus, (3) spacing. (Han-Wen says: for (2), look at
+ * beam engraver.) For example, currently only the accidental for the
+ * second note (cp. the above FIXME) is printed. These issues should
+ * be resolved by some sort of ligature context that encloses use of
+ * this engraver, using syntax like: \ligature { e \~ c }.
*
* TODO: Do not allow a series of adjacent porrectus requests, as in:
- * e \porrectus d \porrectus c.
- */
+ * e \~ d \~ c.
+ *
+ * TODO: Junk duplicate (or rather triple) implementation of
+ * create_ledger_line in porrectus.cc, custos.cc and note-head.cc. */
#include "staff-symbol-referencer.hh"
#include "porrectus.hh"
Note_req *note_req_l_ = dynamic_cast <Note_req *> (info_l_.req_l_);
if (!note_req_l_)
return;
- left_heads_.push (PHead_melodic_tuple (info_l_.elem_l_, note_req_l_,
- now_mom () +
- note_req_l_->length_mom ()));
+ right_heads_.push (PHead_melodic_tuple (info_l_.elem_l_, note_req_l_,
+ now_mom () +
+ note_req_l_->length_mom ()));
}
}
{
left_heads_.sort (PHead_melodic_tuple::pitch_compare);
right_heads_.sort (PHead_melodic_tuple::pitch_compare);
-
- SCM head_list = SCM_EOL;
-
int i = left_heads_.size () - 1;
int j = right_heads_.size () - 1;
while ((i >= 0) && (j >= 0))
{
- head_list =
- gh_cons (gh_cons (right_heads_[j].head_l_->self_scm (),
- left_heads_[i].head_l_->self_scm ()),
- head_list);
-
- past_notes_pq_. insert (left_heads_[i]);
- left_heads_.del (i);
- right_heads_.del (j);
- i--;
- j--;
- }
-
- for (SCM s = head_list; gh_pair_p (s); s = gh_cdr (s))
- {
- SCM caar = gh_caar (s);
- SCM cdar = gh_cdar (s);
-
- Item *left_head = dynamic_cast<Item*> (unsmob_grob (caar));
- Item *right_head = dynamic_cast<Item*> (unsmob_grob (cdar));
+ Item *left_head = dynamic_cast<Item*> (left_heads_[i].head_l_);
+ Item *right_head = dynamic_cast<Item*> (right_heads_[j].head_l_);
left_head->set_grob_property("transparent", gh_bool2scm(true));
right_head->set_grob_property("transparent", gh_bool2scm(true));
Grob *porrectus_p_ = new Item (get_property ("Porrectus"));
- Porrectus::set_left_head(porrectus_p_, caar);
- Porrectus::set_right_head(porrectus_p_, cdar);
+ Porrectus::set_left_head(porrectus_p_, left_head);
+ Porrectus::set_right_head(porrectus_p_, right_head);
porrectus_p_arr_.push (porrectus_p_);
- announce_grob (porrectus_p_, 0);
+ announce_grob (porrectus_p_, porrectus_req_l_);
+
+ past_notes_pq_. insert (right_heads_[i]);
+ left_heads_.del (i);
+ right_heads_.del (j);
+ i--;
+ j--;
}
}
}
void
Porrectus_engraver::stop_translation_timestep ()
{
- for (int i = 0; i < left_heads_.size (); i++)
+ for (int i = 0; i < right_heads_.size (); i++)
{
- past_notes_pq_.insert (left_heads_[i]);
+ past_notes_pq_.insert (right_heads_[i]);
}
- left_heads_.clear ();
+ right_heads_.clear ();
for (int i = 0; i < porrectus_p_arr_.size (); i++)
{
while (past_notes_pq_.size () && past_notes_pq_.front ().end_ < now)
past_notes_pq_.delmin ();
- right_heads_.clear ();
+ left_heads_.clear ();
while (past_notes_pq_.size () &&
(past_notes_pq_.front ().end_ == now))
- right_heads_.push (past_notes_pq_.get ());
+ left_heads_.push (past_notes_pq_.get ());
}
ADD_THIS_TRANSLATOR (Porrectus_engraver);
#include "direction.hh"
#include "bezier.hh"
#include "font-interface.hh"
+#include "paper-def.hh"
#include "math.h" // rint
void
-Porrectus::set_left_head (Grob *me, SCM left_head)
+Porrectus::set_left_head (Grob *me, Item *left_head)
{
- if (left_head == SCM_EOL)
+ if (left_head != 0)
{
- warning (_ ("(left_head == SCM_EOL) (ignored)"));
+ me->set_grob_property ("left-head", left_head->self_scm());
+ }
+ else
+ {
+ programming_error (_ ("(left_head == 0)"));
+ me->set_grob_property ("left-head", SCM_EOL);
}
- me->set_grob_property ("left-head", left_head);
}
-SCM
+Item *
Porrectus::get_left_head (Grob *me)
{
- SCM left_head = me->get_grob_property ("left-head");
- return left_head;
+ SCM left_head_scm = me->get_grob_property ("left-head");
+ if (left_head_scm == SCM_EOL)
+ {
+ programming_error (_ ("undefined left_head"));
+ return 0;
+ }
+ else
+ {
+ Item *left_head = dynamic_cast<Item*> (unsmob_grob (left_head_scm));
+ return left_head;
+ }
}
void
-Porrectus::set_right_head (Grob *me, SCM right_head)
+Porrectus::set_right_head (Grob *me, Item *right_head)
{
- if (right_head == SCM_EOL)
+ if (right_head != 0)
+ {
+ me->set_grob_property ("right-head", right_head->self_scm());
+ }
+ else
{
- warning (_ ("(right_head == SCM_EOL) (ignored)"));
+ programming_error (_ ("(right_head == 0)"));
+ me->set_grob_property ("right-head", SCM_EOL);
}
- me->set_grob_property ("right-head", right_head);
}
-SCM
+Item *
Porrectus::get_right_head (Grob *me)
{
- SCM right_head = me->get_grob_property ("right-head");
- return right_head;
+ SCM right_head_scm = me->get_grob_property ("right-head");
+ if (right_head_scm == SCM_EOL)
+ {
+ programming_error (_ ("undefined right_head"));
+ return 0;
+ }
+ else
+ {
+ Item *right_head = dynamic_cast<Item*> (unsmob_grob (right_head_scm));
+ return right_head;
+ }
}
// Uugh. The following two functions are almost duplicated code from
if (!stem_direction)
stem_direction = DOWN;
- SCM left_head_scm = get_left_head (me);
- SCM right_head_scm = get_right_head (me);
- if ((left_head_scm == SCM_EOL) || (right_head_scm == SCM_EOL))
- {
- warning (_ ("junking lonely porrectus"));
- return SCM_EOL;
- }
-
- Item *left_head = dynamic_cast<Item*> (unsmob_grob (left_head_scm));
- Item *right_head = dynamic_cast<Item*> (unsmob_grob (right_head_scm));
+ Item *left_head = get_left_head (me);
+ Item *right_head = get_right_head (me);
if (!left_head || !right_head)
{
warning (_ ("junking lonely porrectus"));
+ me->suicide ();
return SCM_EOL;
}
Real interval = right_position_f - left_position_f;
Molecule molecule;
+
+ SCM line_thickness_scm = me->get_grob_property ("line-thickness");
+ Real line_thickness;
+ if (gh_number_p (line_thickness_scm))
+ {
+ line_thickness = gh_scm2double (line_thickness_scm);
+ }
+ else
+ {
+ line_thickness = 1.0;
+ }
+ Real thickness =
+ line_thickness * me->paper_l ()->get_var ("stafflinethickness");
+
+ SCM porrectus_width_scm = me->get_grob_property ("porrectus-width");
+ Real porrectus_width;
+ if (gh_number_p (porrectus_width_scm))
+ {
+ porrectus_width = gh_scm2double (porrectus_width_scm);
+ }
+ else
+ {
+ porrectus_width = 2.4;
+ }
+ Real width = porrectus_width * Staff_symbol_referencer::staff_space (me);
+
if (String::compare_i (style, "vaticana") == 0)
- molecule = brew_vaticana_molecule (me, solid, add_stem, stem_direction,
- interval);
+ molecule = brew_vaticana_molecule (me, interval,
+ solid, width, thickness,
+ add_stem, stem_direction);
else if (String::compare_i (style, "mensural") == 0)
- molecule = brew_mensural_molecule (me, solid, add_stem, stem_direction,
- interval);
+ molecule = brew_mensural_molecule (me, interval,
+ solid, width, thickness,
+ add_stem, stem_direction);
else
return SCM_EOL;
Molecule
Porrectus::brew_vaticana_molecule (Item *me,
+ Real interval,
bool solid,
+ Real width,
+ Real thickness,
bool add_stem,
- Direction stem_direction,
- Real interval)
+ Direction stem_direction)
{
Real space = Staff_symbol_referencer::staff_space (me);
- Real line_thickness = space/6;
- Real width = 2.4 * space;
Molecule molecule = Molecule ();
if (interval >= 0.0)
{
- warning (_ ("ascending vaticana style porrectus (ignored)"));
+ warning (_ ("ascending vaticana style porrectus"));
}
if (add_stem)
{
bool consider_interval =
- ((stem_direction == DOWN) && (interval < 0.0)) ||
- ((stem_direction == UP) && (interval > 0.0));
+ stem_direction * interval > 0.0;
- Interval stem_box_x (-line_thickness/2, +line_thickness/2);
+ Interval stem_box_x (-thickness/2, +thickness/2);
Interval stem_box_y;
if (consider_interval)
molecule.add_molecule(stem);
}
- Box vertical_edge (Interval (-line_thickness/2, +line_thickness/2),
- Interval (-4*line_thickness/2, +4*line_thickness/2));
+ Box vertical_edge (Interval (-thickness/2, +thickness/2),
+ Interval (-4*thickness/2, +4*thickness/2));
Molecule left_edge = Lookup::filledbox (vertical_edge);
Molecule right_edge = Lookup::filledbox (vertical_edge);
right_edge.translate_axis (width, X_AXIS);
bezier.control_[3] = Offset (1.00 * width, interval / 2.0);
Molecule slice;
- slice = Lookup::slur (bezier, 0.0, line_thickness);
- slice.translate_axis (-3 * line_thickness/2, Y_AXIS);
+ slice = Lookup::slur (bezier, 0.0, thickness);
+ slice.translate_axis (-3 * thickness/2, Y_AXIS);
molecule.add_molecule (slice);
if (solid)
for (int i = -2; i < +2; i++)
{
- slice = Lookup::slur (bezier, 0.0, line_thickness);
- slice.translate_axis (i * line_thickness/2, Y_AXIS);
+ slice = Lookup::slur (bezier, 0.0, thickness);
+ slice.translate_axis (i * thickness/2, Y_AXIS);
molecule.add_molecule (slice);
}
- slice = Lookup::slur (bezier, 0.0, line_thickness);
- slice.translate_axis (+3 * line_thickness/2, Y_AXIS);
+ slice = Lookup::slur (bezier, 0.0, thickness);
+ slice.translate_axis (+3 * thickness/2, Y_AXIS);
molecule.add_molecule (slice);
return molecule;
Molecule
Porrectus::brew_mensural_molecule (Item *me,
+ Real interval,
bool solid,
+ Real width,
+ Real thickness,
bool add_stem,
- Direction stem_direction,
- Real interval)
+ Direction stem_direction)
{
Real space = Staff_symbol_referencer::staff_space (me);
- Real line_thickness = space/6;
- Real width = 2.4 * space;
Molecule molecule = Molecule ();
if (add_stem)
// brew_vaticana_molecule, but may eventually be changed.
bool consider_interval =
- ((stem_direction == DOWN) && (interval < 0.0)) ||
- ((stem_direction == UP) && (interval > 0.0));
+ stem_direction * interval > 0.0;
- Interval stem_box_x (0, line_thickness);
+ Interval stem_box_x (0, thickness);
Interval stem_box_y;
if (consider_interval)
Real slope = (interval / 2.0) / width;
- Molecule left_edge =
- brew_horizontal_slope (line_thickness, slope, 3.5 * line_thickness);
- left_edge.translate_axis (0.25 * line_thickness, Y_AXIS);
- molecule.add_molecule(left_edge);
-
- Molecule right_edge =
- brew_horizontal_slope (line_thickness, slope, 3.5 * line_thickness);
- right_edge.translate_axis (width - line_thickness, X_AXIS);
- right_edge.translate_axis (interval / 2.0 * (1.0 - (line_thickness/width)) +
- 0.25 * line_thickness, Y_AXIS);
- molecule.add_molecule(right_edge);
-
- Molecule bottom_edge =
- Porrectus::brew_horizontal_slope (width, slope, line_thickness);
- bottom_edge.translate_axis (-3 * line_thickness/2, Y_AXIS);
- molecule.add_molecule (bottom_edge);
-
- Molecule top_edge =
- Porrectus::brew_horizontal_slope (width, slope, line_thickness);
- top_edge.translate_axis (+3 * line_thickness/2, Y_AXIS);
- molecule.add_molecule (top_edge);
+ // Compensate optical illusion regarding vertical position of left
+ // and right endings due to slope.
+ Real ypos_correction = -0.1*space * sign(slope);
+ Real slope_correction = 0.2*space * sign(slope);
+ Real corrected_slope = slope + slope_correction/width;
if (solid)
{
- Molecule core =
- Porrectus::brew_horizontal_slope (width, slope, 6 * line_thickness/2);
- core.translate_axis (-line_thickness/2, Y_AXIS);
- molecule.add_molecule (core);
+ Molecule solid_head =
+ brew_horizontal_slope (width, corrected_slope, 0.6*space);
+ molecule.add_molecule (solid_head);
}
-
+ else
+ {
+ Molecule left_edge =
+ brew_horizontal_slope (thickness, corrected_slope, 0.6*space);
+ molecule.add_molecule(left_edge);
+
+ Molecule right_edge =
+ brew_horizontal_slope (thickness, corrected_slope, 0.6*space);
+ right_edge.translate_axis (width-thickness, X_AXIS);
+ right_edge.translate_axis (corrected_slope * (width-thickness), Y_AXIS);
+ molecule.add_molecule(right_edge);
+
+ Molecule bottom_edge =
+ brew_horizontal_slope (width, corrected_slope, thickness);
+ bottom_edge.translate_axis (-0.3*space, Y_AXIS);
+ molecule.add_molecule (bottom_edge);
+
+ Molecule top_edge =
+ brew_horizontal_slope (width, corrected_slope, thickness);
+ top_edge.translate_axis (+0.3*space, Y_AXIS);
+ molecule.add_molecule (top_edge);
+ }
+ molecule.translate_axis (ypos_correction, Y_AXIS);
return molecule;
}
+/*
+ * Horizontal Slope:
+ *
+ * /| ^
+ * / | |
+ * / | | thickness
+ * / | |
+ * / | v
+ * | /
+ * | /
+ * (0,0) x /slope=dy/dx
+ * | /
+ * |/
+ *
+ * <----->
+ * width
+ */
Molecule
-Porrectus::brew_horizontal_slope(Real width, Real slope, Real line_thickness)
+Porrectus::brew_horizontal_slope(Real width, Real slope, Real thickness)
{
SCM width_scm = gh_double2scm (width);
SCM slope_scm = gh_double2scm (slope);
- SCM line_thickness_scm = gh_double2scm (line_thickness);
+ SCM thickness_scm = gh_double2scm (thickness);
SCM horizontal_slope = gh_list (ly_symbol2scm ("beam"),
width_scm, slope_scm,
- line_thickness_scm, SCM_UNDEFINED);
+ thickness_scm, SCM_UNDEFINED);
Box b (Interval (0, width),
- Interval (0, width * slope +
- sqrt (sqr(line_thickness/slope) + sqr (line_thickness))));
+ Interval (-thickness/2, thickness/2 + width*slope));
return Molecule (b, horizontal_slope);
}