X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fvaticana-ligature.cc;h=4995aad2f04ddd0b8920c57789f36516f66bf5fd;hb=5b4b0d6e9a197e8f9eb085b7c2ad78b8be3e5cfc;hp=916c20e3d890a106118fd256f5b111ac9e57fe78;hpb=7eabfd71691d01bbcda34f9a8921d4b555942cd6;p=lilypond.git diff --git a/lily/vaticana-ligature.cc b/lily/vaticana-ligature.cc index 916c20e3d8..4995aad2f0 100644 --- a/lily/vaticana-ligature.cc +++ b/lily/vaticana-ligature.cc @@ -1,84 +1,114 @@ /* vaticana-ligature.cc -- implement Vaticana_ligature - + source file of the GNU LilyPond music typesetter - - (c) 2003 Juergen Reuter + + (c) 2003--2008 Juergen Reuter */ -#include -#include "item.hh" #include "vaticana-ligature.hh" + +#include "bezier.hh" #include "font-interface.hh" -#include "molecule.hh" +#include "international.hh" +#include "item.hh" #include "lookup.hh" -#include "staff-symbol-referencer.hh" #include "note-head.hh" -#include "paper-def.hh" -#include "bezier.hh" +#include "output-def.hh" +#include "staff-symbol-referencer.hh" #include "warn.hh" -/* - * TODO: move this function to class Lookup? - */ -Molecule -vaticana_brew_flexa (Grob *me, - Real interval, - bool solid, - Real width, +Stencil +vaticana_brew_cauda (Grob *me, + int pos, + int delta_pitch, Real thickness, - bool add_stem, - Direction stem_direction) + Real blotdiameter) { - if (interval >= 0.0) + bool on_staffline = Staff_symbol_referencer::on_line (me, pos); + int interspaces = Staff_symbol_referencer::line_count (me) - 1; + bool above_staff = pos > interspaces; + + if (delta_pitch > -1) { - me->warning (_ ("ascending vaticana style flexa")); + me->programming_error ("flexa cauda: invalid delta_pitch; assuming -1"); + delta_pitch = -1; } - - Real space = Staff_symbol_referencer::staff_space (me); - Molecule molecule = Molecule (); - Real right_height = 0.6 * space; - - // Compensate thickness that appears to be smaller in steep section - // of bend. - Real left_height = right_height + min (0.12 * abs(interval), 0.3) * space; - - if (add_stem) + Real length; + if (on_staffline) + { + if (delta_pitch >= -1) + length = 1.30; + else if (delta_pitch >= -2) + length = 1.35; + else + length = 1.85; + } + else { - bool consider_interval = - stem_direction * interval > 0.0; - - Interval stem_box_x (0, thickness); - Interval stem_box_y; - - if (consider_interval) - { - Real y_length = max (abs(interval)/2.0*space + - (right_height-left_height), - 1.2*space); - stem_box_y = Interval (0, y_length); - } + if (delta_pitch >= -1) + if (above_staff) + length = 1.30; + else + length = 1.00; + else if (delta_pitch >= -2) + length = 1.35; + else if (delta_pitch >= -3) + length = 1.50; else - stem_box_y = Interval (0, space); + length = 1.85; + } + Box cauda_box (Interval (0, thickness), Interval (-length, 0)); + return Lookup::round_filled_box (cauda_box, blotdiameter); +} - Real y_correction = - (stem_direction == UP) ? - +0.5*left_height : - -0.5*left_height - stem_box_y.length(); +/* + * TODO: move this function to class Lookup? + */ +Stencil +vaticana_brew_flexa (Grob *me, + bool solid, + Real line_thickness) +{ + Real staff_space = Staff_symbol_referencer::staff_space (me); + Stencil stencil; + Real right_height = 0.6 * staff_space; - Box stem_box (stem_box_x, stem_box_y); - Molecule stem = Lookup::filledbox (stem_box); - stem.translate_axis (y_correction, Y_AXIS); - molecule.add_molecule(stem); + Real interval; + SCM flexa_height_scm = me->get_property ("flexa-height"); + if (flexa_height_scm != SCM_EOL) + interval = scm_to_int (flexa_height_scm); + else + { + me->warning ("Vaticana_ligature: " + + _ ("flexa-height undefined; assuming 0")); + interval = 0.0; } - // Compensate optical illusion regarding vertical position of left - // and right endings due to curved shape. - Real ypos_correction = -0.1*space * sign(interval); - Real interval_correction = 0.2*space * sign(interval); - Real corrected_interval = interval*space + interval_correction; - - // middle curve of flexa + if (interval >= 0.0) + me->warning (_ ("ascending vaticana style flexa")); + + Real width = robust_scm2double (me->get_property ("flexa-width"), 2); + + /* + * Compensate curve thickness that appears to be smaller in steep + * section of bend. + */ + Real left_height + = right_height + + min (0.12 * abs (interval), 0.3) * staff_space; + + /* + * Compensate optical illusion regarding vertical position of left + * and right endings due to curved shape. + */ + Real ypos_correction = -0.1 * staff_space * sign (interval); + Real interval_correction = 0.2 * staff_space * sign (interval); + Real corrected_interval = interval * staff_space + interval_correction; + + /* + * middle curve of flexa shape + */ Bezier curve; curve.control_[0] = Offset (0.00 * width, 0.0); curve.control_[1] = Offset (0.33 * width, corrected_interval / 2.0); @@ -88,189 +118,159 @@ vaticana_brew_flexa (Grob *me, Bezier top_curve = curve, bottom_curve = curve; for (int i = 0; i < 4; i++) { - Real thickness = 0.33 * ((3 - i)*left_height + i*right_height); - top_curve.control_[i] += Offset (0, +0.5*thickness); - bottom_curve.control_[i] += Offset (0, -0.5*thickness); + Real curve_thickness = 0.33 * ((3 - i) * left_height + i * right_height); + top_curve.control_[i] += Offset (0, 0.5 * curve_thickness); + bottom_curve.control_[i] -= Offset (0, 0.5 * curve_thickness); } if (solid) { - Molecule solid_head = - Lookup::bezier_sandwich (top_curve, bottom_curve); - molecule.add_molecule (solid_head); + Stencil solid_head + = Lookup::bezier_sandwich (top_curve, bottom_curve); + stencil.add_stencil (solid_head); } else // outline { Bezier inner_top_curve = top_curve; - inner_top_curve.translate (Offset (0.0, -thickness)); - Molecule top_edge = - Lookup::bezier_sandwich (top_curve, inner_top_curve); - molecule.add_molecule(top_edge); + inner_top_curve.translate (Offset (0.0, -line_thickness)); + Stencil top_edge + = Lookup::bezier_sandwich (top_curve, inner_top_curve); + stencil.add_stencil (top_edge); Bezier inner_bottom_curve = bottom_curve; - inner_bottom_curve.translate (Offset (0.0, +thickness)); - Molecule bottom_edge = - Lookup::bezier_sandwich (bottom_curve, inner_bottom_curve); - molecule.add_molecule(bottom_edge); - - // TODO: Use horizontal slope with proper slope value rather - // than filled box for left edge, since the filled box stands - // out from the flexa shape if the interval is big and the line - // thickness small. The difficulty here is to compute a proper - // slope value, as it should roughly be equal with the slope of - // the left end of the bezier curve. - Box left_edge_box (Interval (0, thickness), - Interval (-0.5*left_height, +0.5*left_height)); - Molecule left_edge = Lookup::filledbox (left_edge_box); - molecule.add_molecule(left_edge); - - Box right_edge_box (Interval (-thickness, 0), - Interval (-0.5*right_height, +0.5*right_height)); - Molecule right_edge = Lookup::filledbox (right_edge_box); + inner_bottom_curve.translate (Offset (0.0, +line_thickness)); + Stencil bottom_edge + = Lookup::bezier_sandwich (bottom_curve, inner_bottom_curve); + stencil.add_stencil (bottom_edge); + + /* + * TODO: Use horizontal slope with proper slope value rather + * than filled box for left edge, since the filled box stands + * out from the flexa shape if the interval is big and the line + * thickness small. The difficulty here is to compute a proper + * slope value, as it should roughly be equal with the slope of + * the left end of the bezier curve. + */ + Box left_edge_box (Interval (0, line_thickness), + Interval (-0.5 * left_height, +0.5 * left_height)); + Stencil left_edge = Lookup::filled_box (left_edge_box); + stencil.add_stencil (left_edge); + + Box right_edge_box (Interval (-line_thickness, 0), + Interval (-0.5 * right_height, +0.5 * right_height)); + Stencil right_edge = Lookup::filled_box (right_edge_box); right_edge.translate_axis (width, X_AXIS); right_edge.translate_axis (corrected_interval / 2.0, Y_AXIS); - molecule.add_molecule(right_edge); + stencil.add_stencil (right_edge); } - molecule.translate_axis (ypos_correction, Y_AXIS); - return molecule; + stencil.translate_axis (ypos_correction, Y_AXIS); + return stencil; } -void -vaticana_add_ledger_lines (Grob *me, Molecule *out, int pos, Real offs, - bool ledger_take_space) +Stencil +vaticana_brew_join (Grob *me, int delta_pitch, + Real join_thickness, Real blotdiameter) { - int interspaces = Staff_symbol_referencer::line_count (me)-1; - if (abs (pos) - interspaces > 1) + Real staff_space = Staff_symbol_referencer::staff_space (me); + if (!delta_pitch) { - Interval hd = out->extent (X_AXIS); - Real left_ledger_protusion = hd.length ()/4; - Real right_ledger_protusion = left_ledger_protusion; - - Interval l_extents = Interval (hd[LEFT] - left_ledger_protusion, - hd[RIGHT] + right_ledger_protusion); - Molecule ledger_lines = - Note_head::brew_ledger_lines (me, pos, interspaces, - l_extents, - ledger_take_space); - ledger_lines.translate_axis (offs, Y_AXIS); - out->add_molecule (ledger_lines); + me->programming_error (_ ("Vaticana_ligature: " + "zero join (delta_pitch == 0)")); + return Lookup::blank (Box (Interval (0, 0), Interval (0, 0))); } + Interval x_extent = Interval (0, join_thickness); + Interval y_extent = (delta_pitch > 0) + ? Interval (0, delta_pitch * 0.5 * staff_space) : // ascending join + Interval (delta_pitch * 0.5 * staff_space, 0); // descending join + Box join_box (x_extent, y_extent); + return Lookup::round_filled_box (join_box, blotdiameter); } -Molecule -vaticana_brew_primitive (Grob *me, bool ledger_take_space) +Stencil +vaticana_brew_primitive (Grob *me) { - SCM glyph_name_scm = me->get_grob_property ("glyph-name"); + SCM glyph_name_scm = me->get_property ("glyph-name"); if (glyph_name_scm == SCM_EOL) { - programming_error ("Vaticana_ligature:" - "undefined glyph-name -> ignoring grob"); - return Molecule (); + me->programming_error ("Vaticana_ligature: " + "undefined glyph-name -> ignoring grob"); + return Lookup::blank (Box (Interval (0, 0), Interval (0, 0))); } - String glyph_name = ly_scm2string (glyph_name_scm); - if (!String::compare (glyph_name, "")) - { - // empty head (typically, this is the right side of porrectus - // shape, which is already typeset by the associated left side - // head); nothing left to do - return Molecule (); - } + string glyph_name = ly_scm2string (glyph_name_scm); - Molecule out; - int porrectus_height = 0; - Real thickness = 0.0; - Real porrectus_width = 0.0; - Real staff_space = Staff_symbol_referencer::staff_space (me); + Stencil out; + Real thickness = robust_scm2double (me->get_property ("thickness"), 1); - SCM thickness_scm = me->get_grob_property ("thickness"); - if (thickness_scm != SCM_EOL) - { - thickness = gh_scm2double (thickness_scm); - } + Real line_thickness + = thickness * me->layout ()->get_dimension (ly_symbol2scm ("line-thickness")); + + Real blotdiameter + = (me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter"))); + + int pos = Staff_symbol_referencer::get_rounded_position (me); + + SCM delta_pitch_scm = me->get_property ("delta-position"); + int delta_pitch; + if (delta_pitch_scm != SCM_EOL) + delta_pitch = scm_to_int (delta_pitch_scm); else - { - programming_error (_f ("Vaticana_ligature:" - "thickness undefined; assuming 1.4", - me)); - thickness = 1.4 * me->get_paper ()->get_var ("linethickness"); - } + delta_pitch = 0; + + Real x_offset = robust_scm2double (me->get_property ("x-offset"), 0); - Real x_offset = 0.0; - SCM x_offset_scm = me->get_grob_property ("x-offset"); - if (x_offset_scm != SCM_EOL) + bool add_stem = to_boolean (me->get_property ("add-stem")); + bool add_cauda = to_boolean (me->get_property ("add-cauda")); + bool add_join = to_boolean (me->get_property ("add-join")); + + if (glyph_name == "") { - x_offset = gh_scm2double (x_offset_scm); + /* + * This is an empty head. This typically applies for the right + * side of a curved flexa shape, which is already typeset by the + * associated left side head. The only possible thing left to + * do is to draw a vertical join to the next head. (Urgh: need + * flexa_width.) + */ + Real staff_space = Staff_symbol_referencer::staff_space (me); + Real flexa_width = robust_scm2double (me->get_property ("flexa-width"), 2) * staff_space; + out + = Lookup::blank (Box (Interval (0, 0.5 * flexa_width), Interval (0, 0))); } + else if (glyph_name == "flexa") + out = vaticana_brew_flexa (me, true, line_thickness); else { - programming_error (_f ("Vaticana_ligature:" - "x-offset undefined; assuming 0.0", - me)); + out + = Font_interface::get_default_font (me)-> + find_by_name ("noteheads.s" + glyph_name); } + out.translate_axis (x_offset, X_AXIS); + Real head_width = out.extent (X_AXIS).length (); - if (!String::compare (glyph_name, "porrectus")) + if (add_cauda) { - SCM porrectus_height_scm = me->get_grob_property ("porrectus-height"); - if (porrectus_height_scm != SCM_EOL) - { - porrectus_height = gh_scm2int (porrectus_height_scm); - } - else - { - me->warning ("Vaticana_ligature: " - "porrectus-height undefined; assuming 0"); - } - - SCM porrectus_width_scm = me->get_grob_property ("porrectus-width"); - if (porrectus_width_scm != SCM_EOL) - { - porrectus_width = gh_scm2double (porrectus_width_scm); - } - else - { - me->warning ("Vaticana_ligature:" - "porrectus-width undefined; assuming 2.0"); - porrectus_width = 2.0 * staff_space; - } - - bool add_stem = to_boolean (me->get_grob_property ("add-stem")); - out = vaticana_brew_flexa (me, porrectus_height, true, - porrectus_width, thickness, add_stem, DOWN); - } - else - { - Molecule mol = - Font_interface::get_default_font (me)-> - find_by_name ("noteheads-" + glyph_name); - mol.translate_axis (x_offset, X_AXIS); - out.add_molecule (mol); + Stencil cauda + = vaticana_brew_cauda (me, pos, delta_pitch, + line_thickness, blotdiameter); + out.add_stencil (cauda); } - SCM join_left_scm = me->get_grob_property ("join-left"); - if (join_left_scm != SCM_EOL) + if (add_stem) { - int join_left = gh_scm2int (join_left_scm); - if (!join_left) - programming_error (_f ("Vaticana_ligature: (join_left == 0)")); - Real blotdiameter = (me->get_paper ()->get_var ("blotdiameter")); - Interval x_extent = - Interval (-0.5 * thickness, +0.5 * thickness); - Interval y_extent = (join_left > 0) ? - Interval (-join_left * 0.5 * staff_space, 0) : // ascending join - Interval (0, -join_left * 0.5 * staff_space); // descending join - Box stem_box (x_extent, y_extent); - - Molecule stem = Lookup::roundfilledbox (stem_box, blotdiameter); - out.add_molecule (stem); + Stencil stem + = vaticana_brew_cauda (me, pos, -1, + line_thickness, blotdiameter); + stem.translate_axis (head_width - line_thickness, X_AXIS); + out.add_stencil (stem); } - int pos = (int)rint (Staff_symbol_referencer::get_position (me)); - vaticana_add_ledger_lines(me, &out, pos, 0, ledger_take_space); - if (!String::compare (glyph_name, "porrectus")) + if (add_join) { - pos += porrectus_height; - vaticana_add_ledger_lines(me, &out, pos, 0.5*porrectus_height, ledger_take_space); + Stencil join + = vaticana_brew_join (me, delta_pitch, line_thickness, blotdiameter); + join.translate_axis (head_width - line_thickness, X_AXIS); + out.add_stencil (join); } return out; @@ -281,18 +281,28 @@ SCM Vaticana_ligature::brew_ligature_primitive (SCM smob) { Grob *me = unsmob_grob (smob); - SCM primitive = vaticana_brew_primitive (me, false).smobbed_copy (); + SCM primitive = vaticana_brew_primitive (me).smobbed_copy (); return primitive; } -MAKE_SCHEME_CALLBACK (Vaticana_ligature, brew_molecule, 1); +MAKE_SCHEME_CALLBACK (Vaticana_ligature, print, 1); SCM -Vaticana_ligature::brew_molecule (SCM) +Vaticana_ligature::print (SCM) { return SCM_EOL; } -ADD_INTERFACE (Vaticana_ligature, "vaticana-ligature-interface", - "A vaticana style gregorian ligature", - "glyph-name porrectus-height porrectus-width thickness join-left " - "add-stem x-offset ligature-primitive-callback"); +ADD_INTERFACE (Vaticana_ligature, + "A vaticana style Gregorian ligature.", + + /* properties */ + "glyph-name " + "flexa-height " + "flexa-width " + "thickness " + "add-cauda " + "add-stem " + "add-join " + "delta-position " + "x-offset " + );