From b8991734f29f7487f62f9b5172e04b3cbfc00c39 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Sun, 21 Jul 2002 23:19:19 +0000 Subject: [PATCH] * lily/accidental-placement.cc (position_accidentals): document two bugcases. * lily/skyline.cc (skyline_meshing_distance): bugfixes. --- ChangeLog | 11 ++++ input/regression/accidental-placement.ly | 2 +- lily/accidental-placement.cc | 58 +++++++++++++-------- lily/accidental.cc | 65 +++++++++++++++++++++--- lily/include/accidental-interface.hh | 26 ++++++++++ lily/skyline.cc | 20 +++++--- mf/feta-toevallig.mf | 2 +- 7 files changed, 148 insertions(+), 36 deletions(-) create mode 100644 lily/include/accidental-interface.hh diff --git a/ChangeLog b/ChangeLog index c37fee0484..edcfb73721 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ + +2002-07-22 Han-Wen + + * lily/accidental-placement.cc (position_accidentals): document + two bugcases. + + * lily/skyline.cc (skyline_meshing_distance): bugfixes. + 2002-07-22 Jan Nieuwenhuizen * scripts/lilypond-book.py (make_pixmap): Don't use quiet_system, @@ -11,6 +19,9 @@ 2002-07-21 Han-Wen + * lily/accidental.cc (accurate_boxes): add function to represent + flat with 2 boxes. Improves flat-flat accidental spacing. + * lily/accidental-placement.cc (stagger_apes): try to arrange accs in a C form, with the top accidental closet to the chord. diff --git a/input/regression/accidental-placement.ly b/input/regression/accidental-placement.ly index 6011fcc201..ce86f02981 100644 --- a/input/regression/accidental-placement.ly +++ b/input/regression/accidental-placement.ly @@ -13,7 +13,7 @@ flats in a sixth shoudl be staggered. " - + } diff --git a/lily/accidental-placement.cc b/lily/accidental-placement.cc index 1f102415c5..eae952d0eb 100644 --- a/lily/accidental-placement.cc +++ b/lily/accidental-placement.cc @@ -18,6 +18,7 @@ source file of the GNU LilyPond music typesetter #include "note-column.hh" #include "group-interface.hh" #include "note-collision.hh" +#include "accidental-interface.hh" MAKE_SCHEME_CALLBACK(Accidental_placement,extent_callback, 2); SCM @@ -186,11 +187,9 @@ stagger_apes (Link_array *apes) The naturals should be left of the C as well; they should be separate accs. - TODO: Try to combine Apes before sorting them: this will allow a - better placement. + Note that this placement problem looks NP hard, so we just use a + simple strategy, not an optimal choice. - Note that this placement problem is almost certainly NP hard, so we - just use a simple strategy, not an optimal choice. */ SCM @@ -198,6 +197,10 @@ Accidental_placement::position_accidentals (Grob * me) { SCM accs = me->get_grob_property ("accidentals"); + /* + TODO: there is a bug in this code. If two accs are on the same + Y-position, they share an Ape, and will be pritned in overstrike. + */ Link_array apes; for (SCM s = accs; gh_pair_p (s); s =gh_cdr (s)) { @@ -211,7 +214,7 @@ Accidental_placement::position_accidentals (Grob * me) } - Grob *commony =0 ; + Grob *common[] = {me, 0}; /* First we must extract *all* pointers. We can only determine @@ -224,8 +227,12 @@ Accidental_placement::position_accidentals (Grob * me) for (int j = ape->grobs_.size(); j--;) { Grob * a = ape->grobs_[j]; + + if (common[Y_AXIS]) + common[Y_AXIS] = common[Y_AXIS]->common_refpoint (a, Y_AXIS); + else + common[Y_AXIS] = a; - commony = commony->common_refpoint (a, Y_AXIS); Grob *head = a->get_parent (Y_AXIS); Grob * col = head->get_parent (X_AXIS); @@ -261,7 +268,7 @@ Accidental_placement::position_accidentals (Grob * me) } heads.default_sort(); heads.uniq(); - commony = common_refpoint_of_array (heads, commony, Y_AXIS); + common[Y_AXIS] = common_refpoint_of_array (heads, common[Y_AXIS], Y_AXIS); for (int i= apes.size (); i--;) @@ -273,18 +280,15 @@ Accidental_placement::position_accidentals (Grob * me) for (int j = apes[i]->grobs_.size(); j--;) { Grob * a = apes[i]->grobs_[j]; - Box b; - b[X_AXIS] = a->extent (me, X_AXIS); - b[Y_AXIS] = a->extent (commony, Y_AXIS); - ape->extents_.push (b); + Array boxes = Accidental_interface::accurate_boxes (a, common); - /* - TODO: replace the extents of a flat by combination of two - bboxes, so that we use the shape of the flat better. - */ - insert_extent_into_skyline (&ape->left_skyline_, b, Y_AXIS, LEFT); - insert_extent_into_skyline (&ape->right_skyline_ , b,Y_AXIS, RIGHT); + ape->extents_.concat (boxes); + for (int j = boxes.size(); j--;) + { + insert_extent_into_skyline (&ape->left_skyline_, boxes[j], Y_AXIS, LEFT); + insert_extent_into_skyline (&ape->right_skyline_ , boxes[j], Y_AXIS, RIGHT); + } } } @@ -305,13 +309,13 @@ Accidental_placement::position_accidentals (Grob * me) stagger_apes (&apes); Accidental_placement_entry * head_ape = new Accidental_placement_entry; - Grob *commonx = common_refpoint_of_array (heads, me, X_AXIS); + common[X_AXIS] = common_refpoint_of_array (heads, common[X_AXIS], X_AXIS); Array head_skyline (empty_skyline (LEFT)); Array head_extents; for (int i = heads.size(); i--;) { - Box b(heads[i]->extent (commonx, X_AXIS), - heads[i]->extent (commony, Y_AXIS)); + Box b(heads[i]->extent (common[X_AXIS] , X_AXIS), + heads[i]->extent (common[Y_AXIS], Y_AXIS)); insert_extent_into_skyline (&head_skyline, b , Y_AXIS, LEFT); } @@ -328,7 +332,19 @@ Accidental_placement::position_accidentals (Grob * me) SCM spad = me->get_grob_property ("padding"); if (gh_number_p (spad)) padding = gh_scm2double (spad); - + + + /* + TODO: + + There is a bug in this code: the left_skylines should be + accumulated, otherwise the b will collide with bb in + + bb + b + n + + */ apes.push (head_ape); for (int i= apes.size () -1 ; i-- > 0;) { diff --git a/lily/accidental.cc b/lily/accidental.cc index 3792933d87..39d43277c4 100644 --- a/lily/accidental.cc +++ b/lily/accidental.cc @@ -1,6 +1,7 @@ #include "font-interface.hh" #include "item.hh" #include "molecule.hh" +#include "accidental-interface.hh" /* TODO: insert support for smaller cautionaries, tie-break-reminders. @@ -10,13 +11,7 @@ accidental-placement.cc */ -class Accidental_interface -{ -public: - DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM)); - DECLARE_SCHEME_CALLBACK (after_line_breaking, (SCM)); - static bool has_interface (Grob*); -}; + Molecule parenthesize (Grob*me, Molecule m) @@ -43,7 +38,63 @@ Accidental_interface::after_line_breaking (SCM smob) } return SCM_UNSPECIFIED; } + +Array +Accidental_interface::accurate_boxes (Grob *a,Grob**common) +{ + Box b; + b[X_AXIS] = a->extent (a, X_AXIS); + b[Y_AXIS] = a->extent (a, Y_AXIS); + + Array boxes; + + bool parens = false; + if (to_boolean (a->get_grob_property ("cautionary"))) + { + SCM cstyle = a->get_grob_property ("cautionary-style"); + parens = gh_equal_p (cstyle, ly_symbol2scm ("parentheses")); + + } + + SCM accs = a->get_grob_property ("accidentals"); + SCM scm_style = a->get_grob_property ("style"); + if (!gh_symbol_p (scm_style) + && !parens + && scm_ilength (accs) == 1) + { + if (gh_scm2int (gh_car (accs)) == -1) + { + Box stem = b; + Box bulb = b; + + /* + we could make the stem thinner, but that places the flats + really close. + */ + stem[X_AXIS][RIGHT] *= .5; + bulb[Y_AXIS][UP] *= .35; + + boxes.push (bulb); + boxes.push (stem); + } + /* + TODO: add support for natural, double flat. + */ + } + + if (!boxes.size()) + boxes.push (b); + + Offset o (a->relative_coordinate (common[X_AXIS], X_AXIS), + a->relative_coordinate (common[Y_AXIS], Y_AXIS)); + for(int i = boxes.size(); i--;) + { + boxes[i].translate(o); + } + return boxes; +} + MAKE_SCHEME_CALLBACK (Accidental_interface,brew_molecule,1); SCM Accidental_interface::brew_molecule (SCM smob) diff --git a/lily/include/accidental-interface.hh b/lily/include/accidental-interface.hh new file mode 100644 index 0000000000..c2dd022327 --- /dev/null +++ b/lily/include/accidental-interface.hh @@ -0,0 +1,26 @@ +/* +accidental-interface.hh -- declare Accidental_interface + +source file of the GNU LilyPond music typesetter + +(c) 2002 Han-Wen Nienhuys + + */ + +#ifndef ACCIDENTAL_INTERFACE_HH +#define ACCIDENTAL_INTERFACE_HH + +#include "grob.hh" + +class Accidental_interface +{ +public: + DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM)); + DECLARE_SCHEME_CALLBACK (after_line_breaking, (SCM)); + static bool has_interface (Grob*); + + static Array Accidental_interface::accurate_boxes (Grob *me,Grob**common); +}; + + +#endif diff --git a/lily/skyline.cc b/lily/skyline.cc index 9857fe4955..5fa51eed62 100644 --- a/lily/skyline.cc +++ b/lily/skyline.cc @@ -38,6 +38,8 @@ */ +const Real EPS = 1e-12; + /* TODO: avoid unnecessary fragmentation. @@ -53,27 +55,33 @@ insert_extent_into_skyline (Array *line, Box b, Axis line_axis, return; Real stick_out = b[other_axis (line_axis)][d]; - + + /* + Intersect each segment of LINE with EXTENT, and if non-empty, insert relevant segments. + */ for (int i = line->size(); i--;) { Interval w = line->elem(i).width_; - if (extent[LEFT] > w[RIGHT]) + w.intersect (extent); + + if (extent[LEFT] >= w[RIGHT]) break; - w.intersect (extent); Real my_height = line->elem(i).height_; - if (!w.empty_b () && d* (my_height - stick_out) < 0) + if (!w.empty_b () && + w.length() > EPS + && d* (my_height - stick_out) < 0) { Interval e1 (line->elem(i).width_[LEFT], extent[LEFT]); Interval e3 (extent[RIGHT], line->elem(i).width_[RIGHT]); - if (!e3.empty_b ()) + if (!e3.empty_b () && e3.length() > EPS) line->insert (Skyline_entry (e3, my_height), i+1); line->elem_ref(i).height_ = stick_out; line->elem_ref(i).width_ = w; - if (!e1.empty_b ()) + if (!e1.empty_b () && e1.length() > EPS) line->insert (Skyline_entry (e1, my_height), i ); } diff --git a/mf/feta-toevallig.mf b/mf/feta-toevallig.mf index 3363568582..b9e2b48fab 100644 --- a/mf/feta-toevallig.mf +++ b/mf/feta-toevallig.mf @@ -261,7 +261,7 @@ fet_beginchar("Double Flat", "-2", "flatflat") left_wid = .7; right_wid = .8; overlap = .05; - set_char_box(1.2 stafflinethickness#, (left_wid + right_wid -overlap) *staff_space#, .5 staff_space#, 2 staff_space#); + set_char_box(1.2 stafflinethickness#, (left_wid + right_wid -overlap) *staff_space#, .6 staff_space#, 2 staff_space#); draw_meta_flat(0, left_wid* staff_space, 1/3 staff_space); draw_meta_flat((left_wid - overlap) *staff_space, right_wid *staff_space, 1/3 staff_space); -- 2.39.2