X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fhairpin.cc;h=d4f7e8a6fb04c0f64872dae83c2a05ef4c6e4263;hb=933ea175663dc544f1357dc087a653d8a4e4a7bd;hp=cf81fd6ba4892cab8d04214dad0fdb038850a6ac;hpb=4b40ecf0af9b4ff3fcf4287ae685ac1a9cc89523;p=lilypond.git diff --git a/lily/hairpin.cc b/lily/hairpin.cc index cf81fd6ba4..d4f7e8a6fb 100644 --- a/lily/hairpin.cc +++ b/lily/hairpin.cc @@ -3,97 +3,169 @@ source file of the GNU LilyPond music typesetter - (c) 1997--2000 Han-Wen Nienhuys + (c) 1997--2005 Han-Wen Nienhuys */ -#include "molecule.hh" #include "hairpin.hh" + +#include "staff-symbol-referencer.hh" +#include "line-interface.hh" #include "spanner.hh" #include "font-interface.hh" #include "dimensions.hh" -#include "paper-def.hh" -#include "debug.hh" +#include "output-def.hh" +#include "warn.hh" #include "paper-column.hh" +#include "lookup.hh" +#include "text-item.hh" -MAKE_SCHEME_CALLBACK (Hairpin, brew_molecule, 1); +MAKE_SCHEME_CALLBACK(Hairpin,after_line_breaking,1); SCM -Hairpin::brew_molecule (SCM smob) +Hairpin::after_line_breaking (SCM smob) { - Grob *me= unsmob_grob (smob); - Spanner *spanner = dynamic_cast(me); - - Real line = me->paper_l ()->get_var ("stafflinethickness"); + Spanner *me = dynamic_cast (unsmob_grob (smob)); - SCM s = me->get_grob_property("grow-direction"); - if (!isdir_b (s)) + Drul_array broken; + Drul_array bounds; + Direction d = LEFT; + do + { + bounds[d] = me->get_bound (d); + broken[d] = bounds[d]->break_status_dir () != CENTER; + } + while (flip (&d) != LEFT); + + if (broken[LEFT] + && ly_c_equal_p (bounds[RIGHT]->get_column ()->get_property ("when"), + bounds[LEFT]->get_property ("when"))) { me->suicide (); - return SCM_EOL; } - - Direction grow_dir = to_dir (s); + return SCM_UNSPECIFIED; +} + +MAKE_SCHEME_CALLBACK (Hairpin, print, 1); + +SCM +Hairpin::print (SCM smob) +{ + Spanner *me = dynamic_cast (unsmob_grob (smob)); + + SCM s = me->get_property ("grow-direction"); + if (!is_direction (s)) + { + me->suicide (); + return SCM_EOL; + } - /* Ugh, must be same as Text_spanner::brew_molecule. */ - Real padding = gh_scm2double (me->get_grob_property ("padding")); - Real broken_left = spanner->get_broken_left_end_align (); - Real width = spanner->spanner_length (); - width -= broken_left; + Direction grow_dir = to_dir (s); + Real padding = robust_scm2double (me->get_property ("bound-padding"), 0.5); Drul_array broken; - Drul_array extra_off; + Drul_array bounds; Direction d = LEFT; do { - Item *b = spanner->get_bound (d); - broken[d] = b->break_status_dir () != CENTER; + bounds[d] = me->get_bound (d); + broken[d] = bounds[d]->break_status_dir () != CENTER; + } + while (flip (&d) != LEFT); - if (!broken [d]) + Grob *common = bounds[LEFT]->common_refpoint (bounds[RIGHT], X_AXIS); + Drul_array x_points; + + do + { + Item *b = bounds[d]; + x_points[d] = b->relative_coordinate (common, X_AXIS); + if (broken [d]) { - - Interval e =b->extent (b, X_AXIS); - Real r = 0.0; - if (!e.empty_b ()) - r = e[-d] + padding; - width += d * r; - extra_off[d] = r; + if (d == LEFT) + x_points[d] = b->extent (common, X_AXIS)[RIGHT]; + } + else + { + if (Text_interface::has_interface (b)) + { + Interval e = b->extent (common, X_AXIS); + if (!e.is_empty ()) + x_points[d] = e[-d] - d * padding; + } + else + { + bool neighbor_found = false; + for (SCM adj = me->get_property ("adjacent-hairpins"); + scm_is_pair (adj); adj = scm_cdr (adj)) + { + /* + FIXME: this will fuck up in case of polyphonic + notes in other voices. Need to look at note-columns + in the current staff/voice. + */ + + Spanner *pin = unsmob_spanner (scm_car (adj)); + if (pin + && (pin->get_bound (LEFT)->get_column () == b->get_column () + || pin->get_bound (RIGHT)->get_column () == b->get_column ())) + neighbor_found = true; + } + + /* + If we're hung on a paper column, that means we're not + adjacent to a text-dynamic, and we may move closer. We + make the padding a little smaller, here. + */ + Interval e = robust_relative_extent (b, common, X_AXIS); + x_points[d] + = neighbor_found ? e.center () - d * padding / 3 : e[d]; + } } } while (flip (&d) != LEFT); - // FIXME: ecs tells us - width += gh_scm2double (me->get_grob_property ("width-correct")); - /* /Ugh */ - - - - - + Real width = x_points[RIGHT] - x_points[LEFT]; if (width < 0) { - warning (_ ((grow_dir < 0) ? "decrescendo too small" - : "crescendo too small")); + me->warning (_ ((grow_dir < 0) ? "decrescendo too small" + : "crescendo too small")); width = 0; } bool continued = broken[Direction (-grow_dir)]; - Real height = gh_scm2double (me->get_grob_property ("height")); - Real thick = line * gh_scm2double (me->get_grob_property ("thickness")); - - const char* type = (grow_dir < 0) ? "decrescendo" : "crescendo"; - SCM hairpin = gh_list (ly_symbol2scm (type), - gh_double2scm (thick), - gh_double2scm (width), - gh_double2scm (height), - gh_double2scm (continued ? height/2 : 0.0), - SCM_UNDEFINED); - - Box b (Interval (0, width), Interval (-2*height, 2*height)); - Molecule mol (b, hairpin); - mol.translate_axis (broken_left + extra_off[LEFT], X_AXIS); + Real height = robust_scm2double (me->get_property ("height"), 0.2) * + Staff_symbol_referencer::staff_space (me); + + Real starth, endh; + if (grow_dir < 0) + { + starth = height; + endh = continued ? height / 2 : 0.0; + } + else + { + starth = continued ? height / 2 : 0.0; + endh = height; + } + + /* + should do relative to staff-symbol staff-space? + */ + + Stencil mol; + mol = Line_interface::line (me, Offset (0, starth), Offset (width, endh)); + mol.add_stencil (Line_interface::line (me, + Offset (0, -starth), + Offset (width, -endh))); + mol.translate_axis (x_points[LEFT] + - bounds[LEFT]->relative_coordinate (common, X_AXIS), + X_AXIS); return mol.smobbed_copy (); } +ADD_INTERFACE (Hairpin, "hairpin-interface", + "A hairpin (de)crescendo.", + "grow-direction height bound-padding adjacent-hairpins");