+2003-09-09 Juergen Reuter <reuter@ipd.uka.de>
+
+ * lily/vaticana-ligature-engraver.cc: bugfix: fixed programming
+ error message "flexa-width undefined"
+
+ * lily/vaticana-ligature-engraver.cc, lily/gregorian-ligature.cc,
+ lily/include/gregorian-ligature.hh: print warning when ignoring
+ head prefixes on flexa shapes
+
+ * lily/vaticana-ligature-engraver.cc: bugfix: always add an extra
+ space before a series of inclinatum heads
+
+ * lily/vaticana-ligature-engraver.cc, lily/gregorian-ligature.cc,
+ lily/include/gregorian-ligature.hh: junked AFTER_VIRGA; small
+ cleanups
+
+ * mf/parmesan-custodes.mf: redesigned custos; fixed stem length
+ and char_box
+
2003-09-08 Juergen Reuter <reuter@ipd.uka.de>
* input/regression/breathing-sign.ly: tiny fixes
primitive->warning ("may not apply `\\~' on heads with "
"identical pitch; ignoring `\\~'");
}
- if (prev_prefix_set & VIRGA)
- {
- context_info |= AFTER_VIRGA;
- }
if (prev_prefix_set & DEMINUTUM)
{
context_info |= AFTER_DEMINUTUM;
(c) 2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
*/
#include "grob.hh"
+#include "gregorian-ligature.hh"
+#include "string.hh"
-class Gregorian_ligature {
-public:
- static bool has_interface (Grob *);
-};
+void check_prefix (String name, int mask, int prefix_set, String *str)
+{
+ if (prefix_set & mask)
+ {
+ if (!str->empty_b ())
+ *str += ", ";
+ *str += name;
+ }
+}
+String
+Gregorian_ligature::prefixes_to_str (Grob *primitive)
+{
+ String str;
+ int prefix_set =
+ gh_scm2int (primitive->get_grob_property ("prefix-set"));
+ check_prefix ("virga", VIRGA, prefix_set, &str);
+ check_prefix ("stropha", STROPHA, prefix_set, &str);
+ check_prefix ("inclinatum", INCLINATUM, prefix_set, &str);
+ check_prefix ("auctum", AUCTUM, prefix_set, &str);
+ check_prefix ("descendens", DESCENDENS, prefix_set, &str);
+ check_prefix ("ascendens", ASCENDENS, prefix_set, &str);
+ check_prefix ("oriscus", ORISCUS, prefix_set, &str);
+ check_prefix ("quilisma", QUILISMA, prefix_set, &str);
+ check_prefix ("deminutum", DEMINUTUM, prefix_set, &str);
+ check_prefix ("cavum", CAVUM, prefix_set, &str);
+ check_prefix ("linea", LINEA, prefix_set, &str);
+ return str;
+}
/*
- CHECK ME -- does prefix-set come from here ?
+ CHECK ME -- does prefix-set come from here ?
+
+ In a way, yes. Actually, prefix-set is a property that is written
+ by code of GregorianLigatureEngraver that is virtually invoked by a
+ subclass like VaticanaLigatureEngraver. The property is lateron
+ read by the associated item class, such as VaticanaLigature.--jr
*/
ADD_INTERFACE (Gregorian_ligature, "gregorian-ligature-interface",
"A gregorian ligature",
#ifndef GREGORIAN_LIGATURE_HH
#define GREGORIAN_LIGATURE_HH
+class Gregorian_ligature {
+public:
+ static bool has_interface (Grob *);
+ static String prefixes_to_str (Grob *);
+};
+
/*
* Head prefixes: these bit-mask constants are used to represent
* attributes immediately derived from user input (e.g. by the user
// descending melody
#define FLEXA_RIGHT 0x0008 // this is a head after "\~" in a
// descending melody
-#define AFTER_VIRGA 0x0010 // previous head was a virga
#define AFTER_DEMINUTUM 0x0020 // previous head was a deminutum
#endif /* GREGORIAN_LIGATURE_HH */
return is_stacked_b;
}
-inline int get_context_info (Item *primitive)
+/*
+ * When aligning the heads, sometimes extra space is needed, e.g. to
+ * avoid clashing with the appendix of an adjacent notehead or with an
+ * adjacent notehead itself if it has the same pitch. Extra space is
+ * added at most once between to heads.
+ */
+bool
+need_extra_space (int prev_prefix_set, int prefix_set,
+ int context_info, int delta_pitch)
{
- SCM context_info_scm = primitive->get_grob_property ("context-info");
- if (context_info_scm != SCM_EOL)
- {
- return gh_scm2int (context_info_scm);
- }
- else
- {
- primitive->programming_error ("Vaticana_ligature:"
- "context-info undefined -> "
- "aborting ligature");
- return -1;
- }
+ if (prev_prefix_set & VIRGA)
+ /*
+ * After a virga, make a an additional small space such that the
+ * appendix on the right side of the head does not touch the
+ * following head.
+ */
+ return true;
+
+ if ((prefix_set & INCLINATUM) &&
+ !(prev_prefix_set & INCLINATUM))
+ /*
+ * Always start a series of inclinatum heads with an extra space.
+ */
+ return true;
+
+ if ((context_info & FLEXA_LEFT) && !(context_info & PES_UPPER))
+ /*
+ * Before a flexa (but not within a torculus), make a an
+ * additional small space such that the appendix on the left side
+ * of the flexa does not touch the this head.
+ */
+ return true;
+
+ if (delta_pitch == 0)
+ /*
+ * If there are two adjacent noteheads with the same pitch, add
+ * additional small space between them, such that they do not
+ * touch each other.
+ */
+ return true;
+
+ return false;
}
Real
Real ligature_width = 0.0;
Item *prev_primitive = 0;
+ int prev_prefix_set = 0;
for (int i = 0; i < primitives.size (); i++)
{
Item *primitive = dynamic_cast<Item*> (primitives[i].grob_);
- int context_info;
-
- if ((context_info = get_context_info (primitive)) < 0)
- break; // programming error
+ int prefix_set =
+ gh_scm2int (primitive->get_grob_property ("prefix-set"));
+ int context_info =
+ gh_scm2int (primitive->get_grob_property ("context-info"));
/*
* Get glyph_name, delta_pitch and context_info for this head.
*/
}
- /* Sometimes, extra space is needed, e.g. to avoid clashing with
- the appendix of an adjacent notehead or with an adjacent
- notehead itself if it has the same pitch. */
-
- if (context_info & AFTER_VIRGA)
- {
- /*
- * After a virga, make a an additional small space such that
- * the appendix on the right side of the head does not touch
- * the following head.
- */
- ligature_width += extra_space;
- }
- else if ((context_info & FLEXA_LEFT) && !(context_info & PES_UPPER))
- {
- /*
- * Before a flexa (but not within a torculus), make a an
- * additional small space such that the appendix on the left
- * side of the flexa does not touch the this head.
- */
- ligature_width += extra_space;
- }
- else if (delta_pitch == 0)
- {
- /*
- * If there are two adjacent noteheads with the same pitch,
- * add additional small space between them, such that they
- * do not touch each other.
- */
- ligature_width += extra_space;
- }
+ if (need_extra_space (prev_prefix_set, prefix_set,
+ context_info, delta_pitch))
+ ligature_width += extra_space;
/*
* Horizontally line-up this head to form a ligature.
ligature_width += head_width;
prev_primitive = primitive;
+ prev_prefix_set = prefix_set;
}
/*
return ligature_width;
}
+/*
+ * Depending on the typographical features of a particular ligature
+ * style, some prefixes may be ignored. In particular, if a curved
+ * flexa shape is produced, any prefixes to either of the two
+ * contributing heads that would select a head other than punctum, is
+ * by definition ignored.
+ *
+ * This function prints a warning, if the given primitive is prefixed
+ * such that a head other than punctum would be chosen, if this
+ * primitive were engraved as a stand-alone head.
+ */
+void
+check_for_prefix_loss (Item *primitive)
+{
+ int prefix_set =
+ gh_scm2int (primitive->get_grob_property ("prefix-set"));
+ if (prefix_set & ~PES_OR_FLEXA)
+ {
+ String prefs = Gregorian_ligature::prefixes_to_str (primitive);
+ primitive->warning (_f ("ignored prefix(es) `%s' of this head according "
+ "to restrictions of the selected ligature style",
+ prefs.to_str0 ()));
+ }
+}
+
void
Vaticana_ligature_engraver::transform_heads (Spanner *ligature,
Array<Grob_info> primitives)
*/
if ((context_info & FLEXA_RIGHT) && (context_info & PES_LOWER))
{
- glyph_name = "";
+ check_for_prefix_loss (prev_primitive);
prev_glyph_name = "flexa";
prev_primitive->set_grob_property ("flexa-height",
gh_int2scm (prev_delta_pitch));
bool add_cauda = !(prev_prefix_set && PES_OR_FLEXA);
prev_primitive->set_grob_property ("add-cauda",
gh_bool2scm (add_cauda));
+ check_for_prefix_loss (primitive);
+ glyph_name = "";
+ primitive->set_grob_property ("flexa-width",
+ gh_double2scm (flexa_width));
}
/*
}
else
{
- me->warning ("Vaticana_ligature:"
+ me->warning ("Vaticana_ligature: "
"flexa-width undefined; assuming 2.0");
width = 2.0 * staff_space;
}
SCM glyph_name_scm = me->get_grob_property ("glyph-name");
if (glyph_name_scm == SCM_EOL)
{
- programming_error ("Vaticana_ligature:"
- "undefined glyph-name -> ignoring grob");
+ me->programming_error ("Vaticana_ligature: "
+ "undefined glyph-name -> ignoring grob");
return Molecule ();
}
}
else
{
- programming_error (_f ("Vaticana_ligature:"
- "x-offset undefined; assuming 0.0",
- me));
+ me->programming_error ("Vaticana_ligature: "
+ "x-offset undefined; assuming 0.0");
}
bool add_stem = to_boolean (me->get_grob_property ("add-stem"));
}
else
{
- me->warning ("Vaticana_ligature:"
+ me->warning ("Vaticana_ligature: "
"flexa-width undefined; assuming 2.0");
flexa_width = 2.0 * staff_space;
}
wd# = 0.4a# / a_w;
black_notehead_width# := wd#;
- save stem_size;
+ save offs, stem_size, stem_end, penwidth;
if staffline_adjustment = between_staff_lines:
- stem_size = 0.60;
+ stem_size# = 1.00;
elseif staffline_adjustment = on_staff_line:
- stem_size = 1.10;
+ stem_size# = 1.50;
else: % staffline_adjustment = anywhere
- stem_size = 0.85;
+ stem_size# = 0.85;
+ fi;
+ offs# = direction*0.05ht#;
+ stem_end# = direction*stem_size#*staff_space#;
+
+ define_pixels(offs, stem_end, ht, wd);
+
+ pickup pencircle scaled 0.6stafflinethickness;
+ z1 = (0, offs);
+ z2 = (0.7wd, -offs);
+ z3 = (wd, -offs);
+ penpos1(0.6ht, 90);
+ penpos2(0.6ht, 90);
+ penpos3(0.6ht, 90);
+ penstroke z1e{z2 - z1} .. {right}z2e .. z3e;
+
+ rt x4 = wd;
+ bot y4 = 0;
+ x5 = x4;
+ top y5 = stem_end;
+ draw z4 -- z5;
+
+ if direction > 0:
+ set_char_box(0, wd#, offs#+0.3ht#, stem_end#);
+ else:
+ set_char_box(0, wd#, -stem_end#, offs#+0.3ht#);
fi;
-
- define_pixels(ht, wd);
- pickup pencircle scaled stafflinethickness;
-
- z1 = (0.0wd, +direction*0.05ht);
- z2 = (1.0wd + 0.5stafflinethickness, 0.0ht);
- penpos1(0.5ht, 90);
- penpos2(0.5ht, 90);
- penstroke z1e{z2 - z1} .. {right}z2e;
-
- z3=(1.0wd, +0.0ht);
- z4=(1.0wd, +direction*stem_size*ht);
- draw z3 -- z4;
-
- set_char_box(0, wd#, 0.3 ht#, 0.3 ht#);
fet_endchar;
enddef;