From 987fc85646498b0d8bfa89b85ad1375d942a53f0 Mon Sep 17 00:00:00 2001 From: Mike Solomon Date: Fri, 14 Sep 2012 07:20:22 +0200 Subject: [PATCH] Uses exact horizontal skylines for accidental placement. Removes approximations hardcoded in accidental.cc. Adds right-padding to accidentals' left spines to avoid too-close placement. --- lily/accidental-placement.cc | 35 ++++---- lily/accidental.cc | 127 ++++++++++----------------- lily/include/accidental-interface.hh | 2 +- lily/include/skyline-pair.hh | 2 + lily/include/skyline.hh | 2 + lily/side-position-interface.cc | 58 ++++++------ lily/skyline-pair.cc | 12 +++ lily/skyline.cc | 22 +++++ scm/define-grobs.scm | 1 + 9 files changed, 132 insertions(+), 129 deletions(-) diff --git a/lily/accidental-placement.cc b/lily/accidental-placement.cc index 5b6cfb735b..169fe39fdd 100644 --- a/lily/accidental-placement.cc +++ b/lily/accidental-placement.cc @@ -27,6 +27,7 @@ #include "pointer-group-interface.hh" #include "rhythmic-head.hh" #include "skyline.hh" +#include "skyline-pair.hh" #include "stream-event.hh" #include "warn.hh" @@ -115,16 +116,14 @@ Accidental_placement::get_relevant_accidentals (vector const &elts, Grob struct Accidental_placement_entry { - Skyline left_skyline_; - Skyline right_skyline_; - Interval vertical_extent_; - vector extents_; + Skyline_pair horizontal_skylines_; vector grobs_; }; Real ape_priority (Accidental_placement_entry const *a) { - return a->vertical_extent_[UP]; + // right is up because we're horizontal + return a->horizontal_skylines_.right (); } bool ape_less (Accidental_placement_entry *const &a, @@ -261,17 +260,17 @@ set_ape_skylines (Accidental_placement_entry *ape, offset -= a->extent (a, X_AXIS).length () + padding; } - vector boxes = Accidental_interface::accurate_boxes (a, common); - ape->extents_.insert (ape->extents_.end (), boxes.begin (), boxes.end ()); - - for (vsize j = boxes.size (); j--;) - ape->vertical_extent_.unite (boxes[j][Y_AXIS]); + if (Skyline_pair *sky = Skyline_pair::unsmob (a->get_property ("horizontal-skylines"))) + { + Skyline_pair copy (*sky); + copy.raise (a->relative_coordinate (common[X_AXIS], X_AXIS)); + copy.shift (a->relative_coordinate (common[Y_AXIS], Y_AXIS)); + ape->horizontal_skylines_.merge (copy); + } last_octave = p->get_octave (); last_alteration = p->get_alteration (); } - ape->left_skyline_ = Skyline (ape->extents_, Y_AXIS, LEFT); - ape->right_skyline_ = Skyline (ape->extents_, Y_AXIS, RIGHT); } static vector @@ -375,13 +374,13 @@ position_apes (Grob *me, { Accidental_placement_entry *ape = apes[i]; - Real offset = -ape->right_skyline_.distance (left_skyline); + Real offset = -ape->horizontal_skylines_[RIGHT].distance (left_skyline); if (isinf (offset)) offset = last_offset; else offset -= padding; - Skyline new_left_skyline = ape->left_skyline_; + Skyline new_left_skyline = ape->horizontal_skylines_[LEFT]; new_left_skyline.raise (offset); new_left_skyline.merge (left_skyline); left_skyline = new_left_skyline; @@ -390,8 +389,12 @@ position_apes (Grob *me, for (vsize j = ape->grobs_.size (); j--;) ape->grobs_[j]->translate_axis (offset, X_AXIS); - for (vsize j = ape->extents_.size (); j--;) - width.unite (offset + ape->extents_[j][X_AXIS]); + for (LEFT_and_RIGHT (d)) + { + Real mh = ape->horizontal_skylines_[d].max_height (); + if (!isinf (mh)) + width.add_point (mh); + } last_offset = offset; } diff --git a/lily/accidental.cc b/lily/accidental.cc index 3cc399f84d..0cf270f52a 100644 --- a/lily/accidental.cc +++ b/lily/accidental.cc @@ -25,6 +25,7 @@ #include "paper-column.hh" #include "pitch.hh" #include "stencil.hh" +#include "skyline-pair.hh" Stencil parenthesize (Grob *me, Stencil m) @@ -68,6 +69,53 @@ Accidental_interface::width (SCM smob) return get_extent (unsmob_grob (smob), X_AXIS); } +MAKE_SCHEME_CALLBACK (Accidental_interface, horizontal_skylines, 1); +SCM +Accidental_interface::horizontal_skylines (SCM smob) +{ + Grob *me = unsmob_grob (smob); + if (!me->is_live ()) + return Skyline_pair ().smobbed_copy (); + + /* + * Using the print function may trigger a suicide + * before line breaking. It is therefore `unpure' (c). + * We use the more basic get_stencil. + */ + Stencil *my_stencil = unsmob_stencil (get_stencil (me)); + Skyline_pair *sky = + Skyline_pair::unsmob + (Stencil::skylines_from_stencil + (my_stencil->smobbed_copy (), 0.0, Y_AXIS)); + + if (!sky) + return Skyline_pair ().smobbed_copy (); + + SCM alist = me->get_property ("glyph-name-alist"); + SCM alt = me->get_property ("alteration"); + string glyph_name = robust_scm2string (ly_assoc_get (alt, alist, SCM_BOOL_F), + ""); + if (glyph_name == "accidentals.flat" + || glyph_name == "accidentals.flatflat") + { + // a bit more padding for the right of the stem + // we raise the stem horizontally to a bit less than the average + // horizontal "height" of the entire glyph. This will bring flats + // closer to doubleflats, which looks better (MS opinion). + // this should work for all fonts where the flat is not + // completely bizarre + Real left = my_stencil->extent (X_AXIS)[LEFT]; + Real right = my_stencil->extent (X_AXIS)[RIGHT] * 0.375; + Real down = my_stencil->extent (Y_AXIS)[DOWN]; + Real up = my_stencil->extent (Y_AXIS)[UP]; + vector boxes; + boxes.push_back (Box (Interval (left, right), Interval (down, up))); + Skyline merge_with_me (boxes, Y_AXIS, RIGHT); + (*sky)[RIGHT].merge (merge_with_me); + } + return sky->smobbed_copy (); +} + MAKE_SCHEME_CALLBACK (Accidental_interface, pure_height, 3); SCM Accidental_interface::pure_height (SCM smob, SCM start_scm, SCM) @@ -89,85 +137,6 @@ Accidental_interface::pure_height (SCM smob, SCM start_scm, SCM) return ly_interval2scm (Interval ()); } -vector -Accidental_interface::accurate_boxes (Grob *me, Grob **common) -{ - Box b; - b[X_AXIS] = me->extent (me, X_AXIS); - b[Y_AXIS] = me->extent (me, Y_AXIS); - - vector boxes; - - bool parens = to_boolean (me->get_property ("parenthesized")); - if (!me->is_live ()) - return boxes; - - if (!to_boolean (me->get_property ("restore-first")) - && !parens) - { - SCM alist = me->get_property ("glyph-name-alist"); - SCM alt = me->get_property ("alteration"); - string glyph_name = robust_scm2string (ly_assoc_get (alt, alist, SCM_BOOL_F), - ""); - - if (glyph_name == "accidentals.flat" - || glyph_name == "accidentals.mirroredflat") - { - Box stem = b; - Box bulb = b; - - /* - we could make the stem thinner, but that places the flats - really close. - */ - Direction bulb_dir - = glyph_name == "accidentals.mirroredflat" ? LEFT : RIGHT; - stem[X_AXIS][bulb_dir] = stem[X_AXIS].center (); - - /* - To prevent vertical alignment for 6ths - */ - stem[Y_AXIS] *= 1.1; - bulb[Y_AXIS][UP] *= .35; - - boxes.push_back (bulb); - boxes.push_back (stem); - } - else if (glyph_name == "accidentals.natural") - { - Box lstem = b; - Box rstem = b; - Box belly = b; - - lstem[Y_AXIS] *= 1.1; - rstem[Y_AXIS] *= 1.1; - - belly[Y_AXIS] *= 0.75; - lstem[X_AXIS][RIGHT] *= .33; - rstem[X_AXIS][LEFT] = rstem[X_AXIS].linear_combination (1.0 / 3.0); - lstem[Y_AXIS][DOWN] = belly[Y_AXIS][DOWN]; - rstem[Y_AXIS][UP] = belly[Y_AXIS][UP]; - boxes.push_back (belly); - boxes.push_back (lstem); - boxes.push_back (rstem); - } - /* - TODO: add support for, double flat. - */ - } - - if (!boxes.size ()) - boxes.push_back (b); - - Offset o (me->relative_coordinate (common[X_AXIS], X_AXIS), - me->relative_coordinate (common[Y_AXIS], Y_AXIS)); - - for (vsize i = boxes.size (); i--;) - boxes[i].translate (o); - - return boxes; -} - MAKE_SCHEME_CALLBACK (Accidental_interface, print, 1); SCM Accidental_interface::print (SCM smob) diff --git a/lily/include/accidental-interface.hh b/lily/include/accidental-interface.hh index bf4bfb7a58..9c9b97b580 100644 --- a/lily/include/accidental-interface.hh +++ b/lily/include/accidental-interface.hh @@ -32,11 +32,11 @@ public: DECLARE_SCHEME_CALLBACK (print, (SCM)); DECLARE_SCHEME_CALLBACK (height, (SCM)); DECLARE_SCHEME_CALLBACK (width, (SCM)); + DECLARE_SCHEME_CALLBACK (horizontal_skylines, (SCM)); DECLARE_SCHEME_CALLBACK (pure_height, (SCM, SCM, SCM)); DECLARE_GROB_INTERFACE (); static string get_fontcharname (string style, int alteration); - static vector accurate_boxes (Grob *me, Grob **common); static SCM get_stencil (Grob *me); }; diff --git a/lily/include/skyline-pair.hh b/lily/include/skyline-pair.hh index 1d02674814..566b9be3f7 100644 --- a/lily/include/skyline-pair.hh +++ b/lily/include/skyline-pair.hh @@ -35,6 +35,8 @@ public: Skyline_pair (vector const &skypairs); Skyline_pair (Box const &, Axis a); + Real left () const; + Real right () const; void raise (Real); void shift (Real); void deholify (); diff --git a/lily/include/skyline.hh b/lily/include/skyline.hh index 0cb9fdcc81..c300895fee 100644 --- a/lily/include/skyline.hh +++ b/lily/include/skyline.hh @@ -90,6 +90,8 @@ public: Real height (Real airplane) const; Real max_height () const; Real max_height_position () const; + Real left () const; + Real right () const; void set_minimum_height (Real height); void clear (); bool is_empty () const; diff --git a/lily/side-position-interface.cc b/lily/side-position-interface.cc index 5a0d16606c..b515aa3d52 100644 --- a/lily/side-position-interface.cc +++ b/lily/side-position-interface.cc @@ -259,39 +259,31 @@ Side_position_interface::skyline_side_position (Grob *me, Axis a, if (e) { - if (Accidental_interface::has_interface (e)) - { - vector bs = Accidental_interface::accurate_boxes (e, common); - boxes.insert (boxes.end (), bs.begin (), bs.end ()); - } - else - { - if (Note_column::has_interface (e->get_parent (X_AXIS)) - && to_boolean (me->get_property ("add-stem-support"))) - { - note_column_map[e->get_parent (X_AXIS)].push_back (e); - continue; - } - - Skyline_pair *sp = Skyline_pair::unsmob (e->get_property ("vertical-skylines")); - if (sp && a == Y_AXIS && !pure) - { - Skyline_pair copy = Skyline_pair (*sp); - copy.shift (e->relative_coordinate (common[X_AXIS], X_AXIS)); - copy.raise (e->relative_coordinate (common[Y_AXIS], Y_AXIS)); - skyps.push_back (copy); - continue; - } - Box b; - for (Axis ax = X_AXIS; ax < NO_AXES; incr (ax)) - b[ax] = e->maybe_pure_extent (common[ax], ax, pure, start, end); - - if (b[X_AXIS].is_empty () || b[Y_AXIS].is_empty ()) - continue; - - boxes.push_back (b); - min_h = minmax (dir, b[a][-dir], min_h); - } + if (Note_column::has_interface (e->get_parent (X_AXIS)) + && to_boolean (me->get_property ("add-stem-support"))) + { + note_column_map[e->get_parent (X_AXIS)].push_back (e); + continue; + } + + Skyline_pair *sp = Skyline_pair::unsmob (e->get_property ("vertical-skylines")); + if (sp && a == Y_AXIS && !pure) + { + Skyline_pair copy = Skyline_pair (*sp); + copy.shift (e->relative_coordinate (common[X_AXIS], X_AXIS)); + copy.raise (e->relative_coordinate (common[Y_AXIS], Y_AXIS)); + skyps.push_back (copy); + continue; + } + Box b; + for (Axis ax = X_AXIS; ax < NO_AXES; incr (ax)) + b[ax] = e->maybe_pure_extent (common[ax], ax, pure, start, end); + + if (b[X_AXIS].is_empty () || b[Y_AXIS].is_empty ()) + continue; + + boxes.push_back (b); + min_h = minmax (dir, b[a][-dir], min_h); } } diff --git a/lily/skyline-pair.cc b/lily/skyline-pair.cc index bbfe9234fc..164117c35b 100644 --- a/lily/skyline-pair.cc +++ b/lily/skyline-pair.cc @@ -90,6 +90,18 @@ Skyline_pair::print () const skylines_[DOWN].print (); } +Real +Skyline_pair::left () const +{ + return min (skylines_[UP].left (), skylines_[DOWN].left ()); +} + +Real +Skyline_pair::right () const +{ + return max (skylines_[UP].right (), skylines_[DOWN].right ()); +} + void Skyline_pair::print_points () const { diff --git a/lily/skyline.cc b/lily/skyline.cc index 3501d311ac..1d6e4d5e78 100644 --- a/lily/skyline.cc +++ b/lily/skyline.cc @@ -766,6 +766,28 @@ Skyline::max_height () const return sky_ * ret; } +Real +Skyline::left () const +{ + for (list::const_iterator i (buildings_.begin ()); + i != buildings_.end (); i++) + if (i->y_intercept_ > -infinity_f) + return i->start_; + + return infinity_f; +} + +Real +Skyline::right () const +{ + for (list::const_reverse_iterator i (buildings_.rbegin ()); + i != buildings_.rend (); ++i) + if (i->y_intercept_ > -infinity_f) + return i->end_; + + return -infinity_f; +} + Real Skyline::max_height_position () const { diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm index cc8a735565..cc83a365a8 100644 --- a/scm/define-grobs.scm +++ b/scm/define-grobs.scm @@ -33,6 +33,7 @@ (glyph-name . ,accidental-interface::glyph-name) (glyph-name-alist . ,standard-alteration-glyph-name-alist) (stencil . ,ly:accidental-interface::print) + (horizontal-skylines . ,ly:accidental-interface::horizontal-skylines) (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil) (X-extent . ,ly:accidental-interface::width) (Y-extent . ,ly:accidental-interface::height) -- 2.39.2