From 667d9bdb6227dd10819599c6d069a5eeb67eedd7 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Sun, 21 Apr 2002 13:53:02 +0000 Subject: [PATCH] '' --- ChangeLog | 9 + Documentation/regression-test.tely | 3 +- input/regression/accidental-placement.ly | 15 ++ lily/accidental-engraver.cc | 2 +- lily/accidental-placement.cc | 202 +++++++++++++++++++---- lily/accidental.cc | 16 +- lily/axis-group-engraver.cc | 2 +- lily/axis-group-interface.cc | 16 +- lily/bar-line.cc | 2 +- lily/break-algorithm.cc | 3 +- lily/grob.cc | 41 +++-- lily/include/accidental-placement.hh | 3 +- lily/include/break-algorithm.hh | 4 +- lily/include/duration.hh | 2 +- lily/include/grob.hh | 8 +- lily/include/least-squares.hh | 2 +- lily/include/misc.hh | 2 +- lily/include/simple-spacer.hh | 2 +- lily/include/skyline.hh | 13 +- lily/include/tuplet-bracket.hh | 2 +- lily/item.cc | 4 +- lily/least-squares.cc | 2 +- lily/misc.cc | 35 +--- lily/new-accidental-engraver.cc | 12 +- lily/note-column.cc | 17 +- lily/note-head.cc | 4 +- lily/rest-collision.cc | 15 +- lily/side-position-interface.cc | 10 +- lily/simple-spacer.cc | 4 +- lily/skyline.cc | 60 ++++++- lily/slur.cc | 4 +- lily/tuplet-bracket.cc | 7 +- scm/backend-documentation-lib.scm | 5 +- scm/generate-interface-doc.scm | 52 ------ scm/grob-description.scm | 13 +- scm/grob-property-description.scm | 8 +- scm/lily.scm | 7 +- 37 files changed, 380 insertions(+), 228 deletions(-) create mode 100644 input/regression/accidental-placement.ly diff --git a/ChangeLog b/ChangeLog index 14362a3a16..96c8d53a03 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2002-04-21 Han-Wen + * scm/lily.scm (ly-load): use primitive-load for loading. + + * lily/misc.cc: remove quantise_iv() + + * lily/*.cc: pass read-only arrays by reference. + + * lily/grob.cc (common_refpoint_of_array): new function. Try to + use common_refpoint_of_{array, list} when possible. + * lily/include/accidental-placement.hh: new file. * lily/accidental-placement.cc (alignment_callback): position diff --git a/Documentation/regression-test.tely b/Documentation/regression-test.tely index 3960ac9306..ca57437a83 100644 --- a/Documentation/regression-test.tely +++ b/Documentation/regression-test.tely @@ -50,10 +50,11 @@ documenting bugfixes. @section Accidentals -Accidentals are currently in a development stage. @lilypondfile[printfilename]{accidental.ly} +@lilypondfile[printfilename]{accidental-placement.ly} + @lilypondfile[printfilename]{accidental-single-double.ly} @lilypondfile[printfilename]{accidentals.ly} diff --git a/input/regression/accidental-placement.ly b/input/regression/accidental-placement.ly new file mode 100644 index 0000000000..2f142c59a0 --- /dev/null +++ b/input/regression/accidental-placement.ly @@ -0,0 +1,15 @@ +\header { + texidoc ="Accidentals are placed as closely as possible. +Accidentals in corresponding octaves are aligned." +} + + +\score { \notes \context Voice \relative c' { + cis4 + + + + +} +\paper { linewidth = -1. } + } diff --git a/lily/accidental-engraver.cc b/lily/accidental-engraver.cc index 6ee866df9b..e998a9a434 100644 --- a/lily/accidental-engraver.cc +++ b/lily/accidental-engraver.cc @@ -277,7 +277,7 @@ Accidental_engraver::create_grobs () tie_break_reminder); Side_position_interface::add_support (key_item_p_, support_l); - support_l->set_grob_property ("accidentals-grob", key_item_p_->self_scm ()); + support_l->set_grob_property ("accidental-grob", key_item_p_->self_scm ()); } diff --git a/lily/accidental-placement.cc b/lily/accidental-placement.cc index 3d1179c434..acac43671a 100644 --- a/lily/accidental-placement.cc +++ b/lily/accidental-placement.cc @@ -7,7 +7,8 @@ source file of the GNU LilyPond music typesetter */ - +#include +#include #include "item.hh" #include "skyline.hh" #include "music.hh" @@ -16,6 +17,19 @@ source file of the GNU LilyPond music typesetter #include "accidental-placement.hh" +MAKE_SCHEME_CALLBACK(Accidental_placement,extent_callback, 2); +SCM +Accidental_placement::extent_callback(SCM s, SCM axis) +{ + Grob * me =unsmob_grob (s); + Axis a = Axis (gh_scm2int (axis)); + + assert (a == X_AXIS); + + SCM w = position_accidentals (me); + return w; +} + MAKE_SCHEME_CALLBACK(Accidental_placement,alignment_callback, 2); SCM Accidental_placement::alignment_callback(SCM s, SCM ) @@ -23,16 +37,17 @@ Accidental_placement::alignment_callback(SCM s, SCM ) Grob * me =unsmob_grob (s); Grob * par = me->get_parent (X_AXIS); - if (!to_boolean (par->get_grob_property ("done"))) - { - par->set_grob_property ("done", SCM_BOOL_T); - position_accidentals (par); - } - + if (!to_boolean (par->get_grob_property ("alignment-done"))) + { + par->set_grob_property ("alignment-done", SCM_BOOL_T); + position_accidentals (par); + } return gh_int2scm (0); } + + void Accidental_placement::add_accidental (Grob* me, Grob* a) { @@ -68,7 +83,6 @@ Accidental_placement::add_accidental (Grob* me, Grob* a) me->set_grob_property ("accidentals", accs); } - struct Accidental_placement_entry { Array left_skyline_; @@ -76,16 +90,55 @@ struct Accidental_placement_entry Interval vertical_extent_; Array extents_; Link_array grobs_; + Real offset_; int notename_; + Accidental_placement_entry() + { + offset_ =0.0; + notename_ = -1; + } }; + int ape_compare (Accidental_placement_entry *const &a, Accidental_placement_entry *const &b) { return sign (a->vertical_extent_.length () - b->vertical_extent_.length()); } -void +/* + Return: width as SCM interval. + + + This routine computes placements of accidentals. During + add_accidental(), accidentals are already grouped by note, so that + octaves are placed above each other; they form columns. Then the + columns are sorted: the biggest columns go closest to the note. + Then the columns are spaced as closely as possible (using skyline + spacing). + + + TODO: more advanced placement. Typically, the accs should be placed + to form a C shape, like this + + + ## + b b + # # + b + b b + + 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 is almost certainly NP hard, so we + just use a simple strategy, not an optimal choice. +*/ + +SCM Accidental_placement::position_accidentals (Grob * me) { SCM accs = me->get_grob_property ("accidentals"); @@ -105,20 +158,15 @@ Accidental_placement::position_accidentals (Grob * me) Grob *commony =0 ; for (int i= apes.size (); i--;) - for (int j = apes[i]->grobs_.size(); j--;) - { - Grob * a = apes[i]->grobs_[j]; - - if (commony) - commony =commony->common_refpoint (a, Y_AXIS); - else - commony =a; - } + commony = common_refpoint_of_array (apes[i]->grobs_, commony, Y_AXIS); + Link_array heads; for (int i= apes.size (); i--;) { - Interval y ; - + Accidental_placement_entry * ape = apes[i]; + ape->left_skyline_ = empty_skyline ( LEFT); + ape->right_skyline_ = empty_skyline ( RIGHT); + for (int j = apes[i]->grobs_.size(); j--;) { Grob * a = apes[i]->grobs_[j]; @@ -126,41 +174,127 @@ Accidental_placement::position_accidentals (Grob * me) b[X_AXIS] = a->extent (me, X_AXIS); b[Y_AXIS] = a->extent (commony, Y_AXIS); - y.unite (b[Y_AXIS]); - apes[i]->extents_.push (b); + Grob *head = a->get_parent (Y_AXIS); + heads.push (head); + commony = commony->common_refpoint (head, Y_AXIS); + + ape->extents_.push (b); + + + /* + 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); } + } + for (int i = apes.size(); i--;) + { + Interval y ; + + for (int j = apes[i]->extents_.size(); j--;) + { + y.unite (apes[i]->extents_[j][Y_AXIS]); + } apes[i]->vertical_extent_ = y; } - for (int i= apes.size (); i--;) + apes.sort (&ape_compare); + + Accidental_placement_entry * head_ape = new Accidental_placement_entry; + Grob *commonx = common_refpoint_of_array (heads, me, X_AXIS); + Array head_skyline (empty_skyline (LEFT)); + Array head_extents; + for (int i = heads.size(); i--;) { - Accidental_placement_entry * ape = apes[i]; - ape->left_skyline_ = extents_to_skyline (apes[i]->extents_, Y_AXIS, LEFT); - ape->right_skyline_ = extents_to_skyline (apes[i]->extents_, Y_AXIS, RIGHT); + Box b(heads[i]->extent (commonx, X_AXIS), + heads[i]->extent (commony, Y_AXIS)); + + insert_extent_into_skyline (&head_skyline, b , Y_AXIS, LEFT); } - apes.sort (&ape_compare); + head_ape-> left_skyline_ = head_skyline; + head_ape->offset_ = 0.0; - for (int i= apes.size ()-1; i-- > 0;) + SCM rs = me->get_grob_property ("right-padding"); + if (gh_number_p (rs)) + head_ape->offset_ -= gh_scm2double (rs); + + Real padding = 0.1; + apes.push (head_ape); + for (int i= apes.size () -1 ; i-- > 0;) { Accidental_placement_entry *ape = apes[i]; - Real here = 0.0; - - Real d = skyline_meshing_distance (ape->right_skyline_, apes[i+1]->left_skyline_); + Real d = 0.0; + /* + confusing naming: left_skyline is a skyline pointing to the + left. It is on the right of the curent entry. + */ + + int j = i+1; + do { + Array const *right_sky = + (j < apes.size()) + ? &apes[j]->left_skyline_ + : &head_skyline; + + d = - skyline_meshing_distance (ape->right_skyline_, + *right_sky); + + if (!isinf(d) + || j + 1 == apes.size()) + break; + + j = j+ 1; + } while (1); + + if (isinf(d)) + d = 0.0; + + d -= padding; + ape->offset_ += apes[j]->offset_ + d; + } - here += d; + apes.pop(); + for (int i = apes.size(); i--;) + { + Accidental_placement_entry* ape = apes[i]; for (int j = ape->grobs_.size(); j--;) { - ape->grobs_[j]->translate_axis (here, X_AXIS); + ape->grobs_[j]->translate_axis (ape->offset_, X_AXIS); } } + + Interval left_extent, right_extent; + Accidental_placement_entry *ape = apes[0]; + + for (int i = ape->extents_.size(); i--;) + left_extent.unite (ape->offset_ + ape->extents_[i][X_AXIS]); + + ape = apes.top(); + for (int i = ape->extents_.size(); i--;) + right_extent.unite (ape->offset_ + ape->extents_[i][X_AXIS]); + + SCM ls = me->get_grob_property ("left-padding"); + if (gh_number_p (rs)) + left_extent[LEFT] -= gh_scm2double (ls); + + + Interval width(left_extent[LEFT], right_extent[RIGHT]); + + SCM scm_width = ly_interval2scm (width); + me->set_extent (scm_width, X_AXIS); + for (int i = apes.size(); i--;) delete apes[i]; + + return scm_width; } ADD_INTERFACE(Accidental_placement, "accidental-placement-interface", "Take care of complex accidental collisions.", - "accidentals done") + "left-padding right-padding accidentals alignment-done") diff --git a/lily/accidental.cc b/lily/accidental.cc index 44c26da035..fbd1633ae7 100644 --- a/lily/accidental.cc +++ b/lily/accidental.cc @@ -2,6 +2,14 @@ #include "item.hh" #include "molecule.hh" +/* + TODO: insert support for smaller cautionaries, tie-break-reminders. + Either here or in new-accidental-engraver. + + 'accidentals should go, for a single 'accidental property -- see + accidental-placement.cc + +*/ class Accidental_interface { public: @@ -54,12 +62,14 @@ Accidental_interface::brew_molecule (SCM smob) style + to_str (gh_scm2int(entry)))); - mol.add_at_edge (X_AXIS, RIGHT, acc, 0.0); + mol.add_at_edge (X_AXIS, RIGHT, acc, 0.1); } +#if 0 + // TODO. if (to_boolean (me->get_grob_property ("parenthesize"))) mol = parenthesize (me, mol); - +#endif return mol.smobbed_copy(); } @@ -67,4 +77,4 @@ Accidental_interface::brew_molecule (SCM smob) ADD_INTERFACE(Accidental_interface, "accidental-interface", "a single accidental", - "accidentals parenthesize"); + "style accidentals"); diff --git a/lily/axis-group-engraver.cc b/lily/axis-group-engraver.cc index bd2dcf88ad..09bf8084c8 100644 --- a/lily/axis-group-engraver.cc +++ b/lily/axis-group-engraver.cc @@ -65,7 +65,7 @@ Axis_group_engraver::finalize () if (gh_pair_p (dims) && gh_number_p (ly_car (dims)) && gh_number_p (ly_cdr (dims))) { - staffline_p_->set_extent_callback (Grob::preset_extent_proc, Y_AXIS); + staffline_p_->set_extent (Grob::preset_extent_proc, Y_AXIS); staffline_p_->set_grob_property ("extent-Y", dims); } diff --git a/lily/axis-group-interface.cc b/lily/axis-group-interface.cc index 424eb53330..51e8c2f82e 100644 --- a/lily/axis-group-interface.cc +++ b/lily/axis-group-interface.cc @@ -58,13 +58,7 @@ Axis_group_interface::group_extent_callback (SCM element_smob, SCM scm_axis) Grob *me = unsmob_grob (element_smob); Axis a = (Axis) gh_scm2int (scm_axis); - Grob * common = (Grob*) me; - - for (SCM s = me->get_grob_property ("elements"); gh_pair_p (s); s = ly_cdr (s)) - { - Grob * se = unsmob_grob (ly_car (s)); - common = se->common_refpoint (common, a); - } + Grob * common = common_refpoint_of_list (me->get_grob_property ("elements"), me, a); Real my_coord = me->relative_coordinate (common, a); Interval r (relative_group_extent (a, common, me->get_grob_property ("elements"))); @@ -91,17 +85,17 @@ Axis_group_interface::set_axes (Grob*me,Axis a1, Axis a2) } if (a1 != X_AXIS && a2 != X_AXIS) - me->set_extent_callback (SCM_EOL, X_AXIS); + me->set_extent (SCM_EOL, X_AXIS); if (a1 != Y_AXIS && a2 != Y_AXIS) - me->set_extent_callback (SCM_EOL, Y_AXIS); + me->set_extent (SCM_EOL, Y_AXIS); /* why so convoluted ? (fixme/documentme?) */ if (me->has_extent_callback_b (Grob::molecule_extent_proc, a1)) - me->set_extent_callback (Axis_group_interface::group_extent_callback_proc,a1); + me->set_extent (Axis_group_interface::group_extent_callback_proc,a1); if (me->has_extent_callback_b (Grob::molecule_extent_proc, a2)) - me->set_extent_callback (Axis_group_interface::group_extent_callback_proc,a2); + me->set_extent (Axis_group_interface::group_extent_callback_proc,a2); } Link_array diff --git a/lily/bar-line.cc b/lily/bar-line.cc index ebae578015..e124e3a658 100644 --- a/lily/bar-line.cc +++ b/lily/bar-line.cc @@ -153,7 +153,7 @@ Bar_line::before_line_breaking (SCM smob) if (!gh_string_p (g)) { me->set_grob_property ("molecule-callback", SCM_EOL); - me->set_extent_callback (SCM_EOL, X_AXIS); + me->set_extent (SCM_EOL, X_AXIS); // leave y_extent for spanbar? } diff --git a/lily/break-algorithm.cc b/lily/break-algorithm.cc index ce4c075d8c..7dd25936c3 100644 --- a/lily/break-algorithm.cc +++ b/lily/break-algorithm.cc @@ -56,7 +56,8 @@ Break_algorithm::find_breaks () const Simple_spacer* -Break_algorithm::generate_spacing_problem (Link_array curline, Interval line) const +Break_algorithm::generate_spacing_problem (Link_array const &curline, + Interval line) const { Simple_spacer * sp = new Simple_spacer; diff --git a/lily/grob.cc b/lily/grob.cc index 598c347ec1..814aeee638 100644 --- a/lily/grob.cc +++ b/lily/grob.cc @@ -508,8 +508,8 @@ Grob::suicide () mutable_property_alist_ = SCM_EOL; immutable_property_alist_ = SCM_EOL; - set_extent_callback (SCM_EOL, Y_AXIS); - set_extent_callback (SCM_EOL, X_AXIS); + set_extent (SCM_EOL, Y_AXIS); + set_extent (SCM_EOL, X_AXIS); for (int a= X_AXIS; a <= Y_AXIS; a++) { @@ -662,14 +662,37 @@ Grob::common_refpoint (Grob const* s, Axis a) const Grob * -Grob::common_refpoint (SCM elist, Axis a) const +common_refpoint_of_list (SCM elist, Grob *common, Axis a) { - Grob * common = (Grob*) this; for (; gh_pair_p (elist); elist = ly_cdr (elist)) { Grob * s = unsmob_grob (ly_car (elist)); - if (s) + if (!s) + continue; + if (common) + common = common->common_refpoint (s, a); + else + common = s; + } + + return common; +} + + + +Grob * +common_refpoint_of_array (Link_array const &arr, Grob *common, Axis a) +{ + for (int i = arr.size() ; i--; ) + { + Grob * s = arr[i]; + if (!s) + continue; + + if (common) common = common->common_refpoint (s, a); + else + common = s; } return common; @@ -701,12 +724,6 @@ Grob::has_extent_callback_b (SCM cb, Axis a)const } -bool -Grob::has_extent_callback_b (Axis a) const -{ - return gh_procedure_p (dim_cache_[a].dimension_); -} - bool Grob::has_offset_callback_b (SCM cb, Axis a)const { @@ -714,7 +731,7 @@ Grob::has_offset_callback_b (SCM cb, Axis a)const } void -Grob::set_extent_callback (SCM dc, Axis a) +Grob::set_extent (SCM dc, Axis a) { dim_cache_[a].dimension_ =dc; } diff --git a/lily/include/accidental-placement.hh b/lily/include/accidental-placement.hh index 6eb4b48d95..5b59783ff0 100644 --- a/lily/include/accidental-placement.hh +++ b/lily/include/accidental-placement.hh @@ -16,10 +16,11 @@ class Accidental_placement { public: DECLARE_SCHEME_CALLBACK (alignment_callback, (SCM element, SCM axis)); + DECLARE_SCHEME_CALLBACK (extent_callback, (SCM element, SCM axis)); static void add_accidental (Grob *,Grob* ); - static void position_accidentals (Grob* ); + static SCM position_accidentals (Grob* ); static bool has_interface (Grob*); }; #endif /* ACCIDENTAL_PLACEMENT_HH */ diff --git a/lily/include/break-algorithm.hh b/lily/include/break-algorithm.hh index da181cceaf..67d0c02297 100644 --- a/lily/include/break-algorithm.hh +++ b/lily/include/break-algorithm.hh @@ -37,10 +37,10 @@ protected: void solve_line (Column_x_positions*) const; /// does curline fit on the paper? - bool feasible (Link_array) const; + bool feasible (Link_array const &) const; - Simple_spacer* generate_spacing_problem (Link_array, Interval) const; + Simple_spacer* generate_spacing_problem (Link_array const &, Interval) const; virtual Array do_solve () const=0; diff --git a/lily/include/duration.hh b/lily/include/duration.hh index bab00a6782..c256f74d85 100644 --- a/lily/include/duration.hh +++ b/lily/include/duration.hh @@ -45,7 +45,7 @@ private: #include "compare.hh" INSTANTIATE_COMPARE (Duration, Duration::compare); DECLARE_UNSMOB(Duration,duration); -// int compare (Array*, Array*); + #endif // DURATION_HH diff --git a/lily/include/grob.hh b/lily/include/grob.hh index e15b0ce0ac..083e34ec46 100644 --- a/lily/include/grob.hh +++ b/lily/include/grob.hh @@ -139,6 +139,7 @@ public: Dimension_cache dim_cache_[NO_AXES]; public: + bool empty_b (Axis a) const; Interval extent (Grob * refpoint, Axis) const; @@ -160,14 +161,13 @@ public: Find the group-element which has both #this# and #s# */ Grob*common_refpoint (Grob const* s, Axis a) const; - Grob*common_refpoint (SCM elt_list, Axis a) const; + // duh. slim down interface here. (todo) bool has_offset_callback_b (SCM callback, Axis)const; void add_offset_callback (SCM callback, Axis); bool has_extent_callback_b (SCM, Axis)const; - void set_extent_callback (SCM , Axis); - bool has_extent_callback_b (Axis) const; + void set_extent (SCM , Axis); /** @@ -187,6 +187,8 @@ DECLARE_UNSMOB(Grob,grob); Spanner* unsmob_spanner (SCM ); Item* unsmob_item (SCM ); +Grob*common_refpoint_of_list (SCM elt_list, Grob * , Axis a); +Grob*common_refpoint_of_array (Link_array const&, Grob * , Axis a); #endif // STAFFELEM_HH diff --git a/lily/include/least-squares.hh b/lily/include/least-squares.hh index a7a8b14fec..9d4fe3a984 100644 --- a/lily/include/least-squares.hh +++ b/lily/include/least-squares.hh @@ -13,7 +13,7 @@ /** Least squares minimisation in 2 variables. */ -void minimise_least_squares (Real * coef, Real * offset, Array); +void minimise_least_squares (Real * coef, Real * offset, Array const &); #endif // LEASTSQUARE_HH diff --git a/lily/include/misc.hh b/lily/include/misc.hh index 892dca89f2..811858e4bb 100644 --- a/lily/include/misc.hh +++ b/lily/include/misc.hh @@ -20,7 +20,7 @@ sign (int i) else return 0; } -Interval quantise_iv (Array positions, Real x); + #endif diff --git a/lily/include/simple-spacer.hh b/lily/include/simple-spacer.hh index b658f5354b..cbb9cfe7b0 100644 --- a/lily/include/simple-spacer.hh +++ b/lily/include/simple-spacer.hh @@ -43,7 +43,7 @@ struct Simple_spacer Simple_spacer (); void solve (Column_x_positions *, bool) const; - void add_columns (Link_array); + void add_columns (Link_arrayconst &); void my_solve_linelen (); void my_solve_natural_len (); Real active_springs_stiffness () const; diff --git a/lily/include/skyline.hh b/lily/include/skyline.hh index 0a477b8a7b..a49d50ed7b 100644 --- a/lily/include/skyline.hh +++ b/lily/include/skyline.hh @@ -20,14 +20,15 @@ struct Skyline_entry Skyline_entry (Interval, Real); }; -void -insert_extent_into_skyline (Array *line, Box b, Axis line_axis, - Direction d); + +void insert_extent_into_skyline (Array *line, Box b, Axis line_axis, + Direction d); Array -extents_to_skyline (Array extents, Axis a, Direction d); +extents_to_skyline (Array const & extents, Axis a, Direction d); +Array empty_skyline (Direction d); Real -skyline_meshing_distance (Array buildings, - Array clouds); +skyline_meshing_distance (Array const &buildings, + Array const &clouds); #endif /* SKYLINE_HH */ diff --git a/lily/include/tuplet-bracket.hh b/lily/include/tuplet-bracket.hh index 97c10572dc..dc301fa05e 100644 --- a/lily/include/tuplet-bracket.hh +++ b/lily/include/tuplet-bracket.hh @@ -24,7 +24,7 @@ public: static void add_column (Grob*me,Item*); static void add_beam (Grob*me,Grob*); - static Grob *parallel_beam (Grob *me, Link_array cols, bool *equally_long); + static Grob *parallel_beam (Grob *me, Link_array const&cols, bool *equally_long); static void calc_dy (Grob*,Real *) ; static void calc_position_and_height (Grob*,Real*,Real *dy); diff --git a/lily/item.cc b/lily/item.cc index da1cbfb437..abae1689a6 100644 --- a/lily/item.cc +++ b/lily/item.cc @@ -172,8 +172,8 @@ Item::handle_prebroken_dependencies () suicide (); else if (empty) { - set_extent_callback (SCM_EOL, X_AXIS); - set_extent_callback (SCM_EOL, Y_AXIS); + set_extent (SCM_EOL, X_AXIS); + set_extent (SCM_EOL, Y_AXIS); } else if (trans) set_grob_property ("molecule-callback", SCM_EOL); diff --git a/lily/least-squares.cc b/lily/least-squares.cc index d3f44a4463..8100e7ebb8 100644 --- a/lily/least-squares.cc +++ b/lily/least-squares.cc @@ -13,7 +13,7 @@ void minimise_least_squares (Real * coef, Real * offset, - Array input) + Array const &input) { Real sx = 0.0; Real sy = 0.0; diff --git a/lily/misc.cc b/lily/misc.cc index 38154556fd..370164c7ed 100644 --- a/lily/misc.cc +++ b/lily/misc.cc @@ -20,7 +20,7 @@ intlog2 (int d) int i=0; while ((d != 1)) { - d/= 2; + d /= 2; i++; } @@ -34,36 +34,3 @@ log_2 (double x) return log (x) /log (2.0); } - -static int -comp (Real const &a, Real const &b) -{ - return sign (a-b); -} - -Interval -quantise_iv (Array positions, Real x) -{ - positions.sort (comp); - Real period = positions.top () - positions[0]; - - int n = int ((x - positions[0]) / period); - Real frac = (x - positions[0]) - n * period; - - while (frac < 0) - { - frac += period; - n --; - } - - Real px = frac + positions[0]; - assert (positions[0] <= px && px <= positions.top ()); - int i=0; - for (; i < positions.size () - 1; i++) - { - if (positions[i] <= px && px <= positions[i+1]) - break; - } - - return Interval (positions[i] , positions[i+1]) + period * n; -} diff --git a/lily/new-accidental-engraver.cc b/lily/new-accidental-engraver.cc index a8918d089f..8fe112107e 100644 --- a/lily/new-accidental-engraver.cc +++ b/lily/new-accidental-engraver.cc @@ -292,18 +292,22 @@ New_accidental_engraver::create_grobs () } Accidental_placement::add_accidental (accidental_placement_, a); - - Side_position_interface::add_support (a, support_l); announce_grob (a, SCM_EOL); - // todo: add cautionary option + SCM accs = gh_cons (gh_int2scm (pitch->alteration_i_), SCM_EOL); if (num == 2 && extra_natural_b) accs = gh_cons (gh_int2scm (0), accs); + /* TODO: + + add cautionary option in accidental. + */ + if (tie_break_reminder) ; // TODO. - support_l->set_grob_property ("accidentals-grob", a->self_scm ()); + + support_l->set_grob_property ("accidental-grob", a->self_scm ()); a->set_grob_property ("accidentals", accs); accidental_arr_[i].accidental_ = a; diff --git a/lily/note-column.cc b/lily/note-column.cc index c4dd3bdca7..9e6c4cdc1c 100644 --- a/lily/note-column.cc +++ b/lily/note-column.cc @@ -16,6 +16,7 @@ #include "staff-symbol-referencer.hh" #include "rest.hh" #include "note-head.hh" +#include "accidental-placement.hh" bool Note_column::rest_b (Grob*me) @@ -134,15 +135,23 @@ Grob* Note_column::accidentals (Grob *me) { SCM heads = me->get_grob_property ("note-heads"); + Grob * acc = 0; for (;gh_pair_p (heads); heads =gh_cdr (heads)) { Grob * h = unsmob_grob (gh_car (heads)); - Grob *a = h ? unsmob_grob(h->get_grob_property ("accidentals-grob")) : 0; - if (a) - return a; + acc = h ? unsmob_grob (h->get_grob_property ("accidental-grob")) : 0; + if (acc) + break; } - return 0; + if (!acc) + return 0; + + if (Accidental_placement::has_interface (acc->get_parent (X_AXIS))) + return acc->get_parent (X_AXIS); + + /* compatibility. */ + return acc; } diff --git a/lily/note-head.cc b/lily/note-head.cc index f77eea73c7..23328569c5 100644 --- a/lily/note-head.cc +++ b/lily/note-head.cc @@ -136,7 +136,7 @@ internal_brew_molecule (Grob *me, bool ledger_take_space) Real left_ledger_protusion = hd.length ()/4; Real right_ledger_protusion = left_ledger_protusion; - if (unsmob_grob(me->get_grob_property ("accidentals-grob"))) + if (unsmob_grob(me->get_grob_property ("accidental-grob"))) { /* make a little room for accidentals. @@ -245,4 +245,4 @@ Note_head::stem_attachment_coordinate (Grob *me, Axis a) ADD_INTERFACE (Note_head,"note-head-interface", "Note head", - "accidentals-grob style stem-attachment-function"); + "accidental-grob style stem-attachment-function"); diff --git a/lily/rest-collision.cc b/lily/rest-collision.cc index 2bbb79d07a..49e85e2d95 100644 --- a/lily/rest-collision.cc +++ b/lily/rest-collision.cc @@ -90,19 +90,10 @@ Rest_collision::do_shift (Grob *me, SCM elts) */ Link_array rests; Link_array notes; - Grob * commony = 0; + for (SCM s = elts; gh_pair_p (s); s = ly_cdr (s)) { - Grob * e = unsmob_grob (ly_car (s)); - if (!e) - continue; - - if (!commony) - commony = e; - else - commony= commony->common_refpoint (e, Y_AXIS); - if (unsmob_grob (e->get_grob_property ("rest"))) rests.push (e); else @@ -213,9 +204,7 @@ Rest_collision::do_shift (Grob *me, SCM elts) Real minimum_dist = gh_scm2double (me->get_grob_property ("minimum-distance")) * staff_space; - Grob *common = rcol; - for (int i = 0; i < notes.size (); i++) - common = common->common_refpoint (notes[i], Y_AXIS); + Grob *common = common_refpoint_of_array (notes, rcol, Y_AXIS); Interval notedim; for (int i = 0; i < notes.size (); i++) diff --git a/lily/side-position-interface.cc b/lily/side-position-interface.cc index 825f7a2afd..e68aaf660a 100644 --- a/lily/side-position-interface.cc +++ b/lily/side-position-interface.cc @@ -67,7 +67,7 @@ Side_position_interface::aligned_on_support_extents (SCM element_smob, SCM axis) SCM Side_position_interface::general_side_position (Grob * me, Axis a, bool use_extents) { - Grob *common = me->get_parent (a); + /* As this is only used as a callback, this is called only once. We @@ -79,13 +79,7 @@ Side_position_interface::general_side_position (Grob * me, Axis a, bool use_exte */ SCM support = me->get_grob_property ("side-support-elements"); - // me->remove_grob_property ("side-support-elements"); - for (SCM s = support; s != SCM_EOL; s = ly_cdr (s)) - { - Grob * e = unsmob_grob (ly_car (s)); - if (e) - common = common->common_refpoint (e, a); - } + Grob *common = common_refpoint_of_list (support, me->get_parent (a), a); Interval dim; for (SCM s = support; s != SCM_EOL; s = ly_cdr (s)) diff --git a/lily/simple-spacer.cc b/lily/simple-spacer.cc index 75c2ed7752..b83f13aebf 100644 --- a/lily/simple-spacer.cc +++ b/lily/simple-spacer.cc @@ -216,8 +216,10 @@ Simple_spacer::my_solve_natural_len () } void -Simple_spacer::add_columns (Link_array cols) +Simple_spacer::add_columns (Link_array const &icols) { + Link_array cols(icols); + for (int i = cols.size (); i--;) if (gh_pair_p (cols[i]->get_grob_property ("between-cols"))) { diff --git a/lily/skyline.cc b/lily/skyline.cc index d010bf41c1..cc47448ee9 100644 --- a/lily/skyline.cc +++ b/lily/skyline.cc @@ -8,6 +8,42 @@ #include "skyline.hh" + +/* + A skyline is a shape of the form: + + + ---- + | | + ---------| | + | | + | | + | |______ + --------| |___ + + + + This file deals with building such skyline structure, and computing + the minimum distance between two opposing skylines. + + + Invariants for a skyline: + + skyline[...].width_ forms a partition of the real interval, where + the segments are adjacent, and ascending. Hence we have + + skyline.top().width_[RIGHT] = inf + skyline[0].width_[LEFT] = -inf + + */ + + +/* + TODO: avoid unnecessary fragmentation. + + This is O(n^2), searching and insertion. Could be O(n log n) with + binsearch. +*/ void insert_extent_into_skyline (Array *line, Box b, Axis line_axis, Direction d) @@ -45,8 +81,9 @@ insert_extent_into_skyline (Array *line, Box b, Axis line_axis, } } + Array -extents_to_skyline (Array extents, Axis a, Direction d) +empty_skyline (Direction d) { Array skyline; @@ -57,10 +94,21 @@ extents_to_skyline (Array extents, Axis a, Direction d) e.width_ = i; e.height_ = -d * infinity_f; skyline.push (e); + return skyline; +} + +Array +extents_to_skyline (Array const &extents, Axis a, Direction d) +{ + + Array skyline = empty_skyline(d); /* - This makes a quadratic algorithm -- we could do better (n log (n) ) but that - seems overkill for now. + This makes a cubic algorithm (array insertion is O(n), + searching the array dumbly is O(n), and for n items, we get O(n^3).) + + We could do a lot better (n log (n), using a balanced tree) but + that seems overkill for now. */ for (int j = extents.size(); j--; ) insert_extent_into_skyline (&skyline, extents[j], a, d); @@ -72,10 +120,12 @@ extents_to_skyline (Array extents, Axis a, Direction d) /* minimum distance that can be achieved between baselines. "Clouds" is a skyline pointing down. + + This is an O(n) algorithm. */ Real -skyline_meshing_distance (Array buildings, - Array clouds) +skyline_meshing_distance (Array const &buildings, + Array const &clouds) { int i = buildings.size () -1; int j = clouds.size() -1; diff --git a/lily/slur.cc b/lily/slur.cc index e691c606cc..a714fef166 100644 --- a/lily/slur.cc +++ b/lily/slur.cc @@ -448,8 +448,8 @@ Slur::get_encompass_offset_arr (Grob *me) { Spanner*sp = dynamic_cast (me); SCM eltlist = me->get_grob_property ("note-columns"); - Grob *common[] = {me->common_refpoint (eltlist, X_AXIS), - me->common_refpoint (eltlist, Y_AXIS)}; + Grob *common[] = {common_refpoint_of_list (eltlist, me, X_AXIS), + common_refpoint_of_list (eltlist, me, Y_AXIS)}; common[X_AXIS] = common[X_AXIS]->common_refpoint (sp->get_bound (RIGHT), X_AXIS); diff --git a/lily/tuplet-bracket.cc b/lily/tuplet-bracket.cc index b7cbc2c49b..2b6b6f7cb1 100644 --- a/lily/tuplet-bracket.cc +++ b/lily/tuplet-bracket.cc @@ -55,7 +55,7 @@ get_x_bound_grob (Grob *g, Direction my_dir) Grob* -Tuplet_bracket::parallel_beam (Grob *me, Link_array cols, bool *equally_long) +Tuplet_bracket::parallel_beam (Grob *me, Link_array const &cols, bool *equally_long) { /* ugh: code dup. @@ -251,8 +251,9 @@ Tuplet_bracket::calc_position_and_height (Grob*me,Real *offset, Real * dy) Pointer_group_interface__extract_grobs (me, (Grob*)0, "note-columns"); - Grob * commony = me->common_refpoint (me->get_grob_property ("note-columns"), Y_AXIS); - Grob * commonx = me->common_refpoint (me->get_grob_property ("note-columns"), X_AXIS); + SCM cols = me->get_grob_property ("note-columns"); + Grob * commony = common_refpoint_of_list (cols, me, Y_AXIS); + Grob * commonx = common_refpoint_of_list (cols, me, X_AXIS); Direction dir = Directional_element_interface::get (me); diff --git a/scm/backend-documentation-lib.scm b/scm/backend-documentation-lib.scm index 3e6934c554..645c56c92b 100644 --- a/scm/backend-documentation-lib.scm +++ b/scm/backend-documentation-lib.scm @@ -127,7 +127,7 @@ (if (not (defined? 'standalone)) (begin - (debug-enable 'backtrace) +; (debug-enable 'backtrace) (load "standalone.scm") @@ -187,7 +187,8 @@ )) ;(write (map car interface-description-alist) (current-error-port)) -;(display (lookup-interface 'volta-bracket-interface)) +;(display (lookup-interface 'accidental-placement-interface)) +;(display (document-all-grobs "OO" )) (define (document-all-interfaces name) (string-append diff --git a/scm/generate-interface-doc.scm b/scm/generate-interface-doc.scm index 565f72a240..e69de29bb2 100644 --- a/scm/generate-interface-doc.scm +++ b/scm/generate-interface-doc.scm @@ -1,52 +0,0 @@ - -;;; generate-interface-doc.scm -- Generate list of all intefaces, for refman -;;; -;;; source file of the GNU LilyPond music typesetter -;;; -;;; (c) 2000--2001 Han-Wen Nienhuys -;;; Jan Nieuwenhuizen - -;;; File entry point for generated documentation - -;;; Running LilyPond on this file generates the documentation - - - -;; We use ly-gulp because these files live in -;; -;; PATH=$LILYPONDPREFIX/scm:/scm -;; -(eval-string (ly-gulp-file "documentation-lib.scm")) -(eval-string (ly-gulp-file "engraver-documentation-lib.scm")) -(eval-string (ly-gulp-file "backend-documentation-lib.scm")) - -;;(define no-copies #t) ; from 490 to 410K, but doesn't look nice yet -;; -;; Also, copies of interfaces use up lots more space, but that's -;; functional because the default property values of the interfaces -;; are described... -(define no-copies #f) - -(let* ((doc (string-append - (document-all-interfaces "Full Grob interface list") - ) - ) - (name "interfaces") - (outname (string-append name ".itexi")) - (out (open-output-file outname))) - - (writing-wip outname) - (display - (string-append - ;;(itexi-file-head - ;; - ;; ;; we can't use (dir) and top if we're included by lilypond.tely - ;; "Grob interfaces" name "" - ;; '( - ;; ("Grob interfaces" . "Grob Interfaces") - ;; )) - doc - "\n") - out)) - -(newline (current-error-port)) diff --git a/scm/grob-description.scm b/scm/grob-description.scm index 9cb4c9dd54..351859214f 100644 --- a/scm/grob-description.scm +++ b/scm/grob-description.scm @@ -29,19 +29,14 @@ (Accidental . ( (molecule-callback . ,Accidental_interface::brew_molecule) - (X-offset-callbacks . (,Side_position_interface::aligned_side)) -; (after-line-breaking-callback . ,Local_key_item::after_line_breaking) - (direction . -1) - (left-padding . 0.2) - (right-padding . 0.5) - (paren-cautionaries . #t) (font-family . music) - (meta . ((interfaces . (accidental-interface staff-symbol-referencer-interface font-interface side-position-interface)))) + (meta . ((interfaces . (accidental-interface font-interface)))) )) (AccidentalPlacement . ( - (X-extent-callback . ,Axis_group_interface::group_extent_callback) -; (after-line-breaking-callback . ,Local_key_item::after_line_breaking) + (X-extent-callback . ,Accidental_placement::extent_callback) + (left-padding . 0.2) + (right-padding . 0.5) (meta . ((interfaces . (accidental-placement-interface)))) )) diff --git a/scm/grob-property-description.scm b/scm/grob-property-description.scm index 98ef948989..6eb69c3ac0 100644 --- a/scm/grob-property-description.scm +++ b/scm/grob-property-description.scm @@ -29,7 +29,10 @@ (grob-property-description 'Y-offset-callbacks list? "see @code{X-offset-callbacks}.") (grob-property-description 'accidentals list? "Alist with (PITCH . OPTION-LIST) entries. OPTION-LIST can contain 'cautionary, 'natural -and 'tie-break-reminder ") +and 'tie-break-reminder + +FIXME: outdated. +") (grob-property-description 'add-stem boolean? "Add stem to porrectus?.") (grob-property-description 'adjust-if-on-staffline boolean? "If this grob is on a staff line, adjust its appearance, so that it better fits into the staff. E.g., if set true on stem grobs, flares of mensural flags will always be aligned with the staff lines, regardless if the associated note head is printed on a staff line or inbetween.") (grob-property-description 'after-line-breaking-callback procedure? "Procedure taking a grob as argument. @@ -263,6 +266,7 @@ FIXME: also pair? (cons LEFT RIGHT) (grob-property-description 'old-accidentals list? "list of (pitch, accidental) pairs.") (grob-property-description 'padding number? "add this much extra space between objects that are next to each other.") (grob-property-description 'paren-cautionaries boolean? "Whether to add parenthesis around cautionary accidentals.") + (grob-property-description 'pedal-type symbol? "Style of piano pedal: text, bracket or mixed.") (grob-property-description 'penalty number? "Penalty for breaking at this column. 10000 or more means forbid linebreak, -10000 or less @@ -435,7 +439,7 @@ columns. (grob-property-description 'staff-support boolean? " JUNKME.") (grob-property-description 'script-molecule pair? "index code for script.") -(grob-property-description 'accidentals-grob ly-grob? "accidentals for this note.") +(grob-property-description 'accidental-grob ly-grob? "Accidental for this note.") (grob-property-description 'causes list? "list of cause objects.") (grob-property-description 'flag-count number? "") diff --git a/scm/lily.scm b/scm/lily.scm index 43addde67b..66dae47b15 100644 --- a/scm/lily.scm +++ b/scm/lily.scm @@ -16,7 +16,7 @@ -(debug-enable 'backtrace) +;(debug-enable 'backtrace) (define point-and-click #f) @@ -113,7 +113,10 @@ (symbol->string (car y)))) -(define (ly-load x) (eval-string (ly-gulp-file x))) +(define (ly-load x) + (primitive-load (%search-load-path x)) + + ) (ly-load "output-lib.scm") -- 2.39.5