From f93ba9a50c9da04f9ffd8944753f60e6513c5730 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Tue, 23 Apr 2002 09:51:08 +0000 Subject: [PATCH] * lily/stem.cc (head_count): Change function name. Change property to #'note-heads i.s.o. #'heads. (position_noteheads): Kern noteheads for invisible stems. (before_line_breaking): Do position_noteheads() for whole note heads too. * lily/accidental-placement.cc (position_accidentals): First determine refpoints, only then determine extents. --- ChangeLog | 11 +++ flower/include/interval.hh | 2 +- input/regression/accidental-placement.ly | 1 + input/regression/completion-heads.ly | 24 +++++++ input/regression/note-head-chord.ly | 16 +++++ lily/accidental-placement.cc | 91 +++++++++++++++--------- lily/auto-beam-engraver.cc | 2 +- lily/include/stem.hh | 2 +- lily/skyline.cc | 2 +- lily/stem.cc | 59 +++++++++++---- mf/feta-nummer16.mf | 2 + mf/feta-nummer20.mf | 2 + mf/feta-nummer23.mf | 2 + mf/feta-nummer26.mf | 2 + scm/grob-property-description.scm | 6 +- scripts/lilypond-book.py | 2 +- 16 files changed, 167 insertions(+), 59 deletions(-) create mode 100644 input/regression/completion-heads.ly create mode 100644 input/regression/note-head-chord.ly create mode 100644 mf/feta-nummer16.mf create mode 100644 mf/feta-nummer20.mf create mode 100644 mf/feta-nummer23.mf create mode 100644 mf/feta-nummer26.mf diff --git a/ChangeLog b/ChangeLog index 70a650e608..cf7b8cb15d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2002-04-23 Han-Wen Nienhuys + + * lily/stem.cc (head_count): Change function name. Change property + to #'note-heads i.s.o. #'heads. + (position_noteheads): Kern noteheads for invisible stems. + (before_line_breaking): Do position_noteheads() for whole note + heads too. + + * lily/accidental-placement.cc (position_accidentals): First + determine refpoints, only then determine extents. + 2002-04-22 Han-Wen Nienhuys * lily/accidental-placement.cc (position_accidentals): use all diff --git a/flower/include/interval.hh b/flower/include/interval.hh index 261a1c37af..c4e9d4e718 100644 --- a/flower/include/interval.hh +++ b/flower/include/interval.hh @@ -24,7 +24,7 @@ struct Interval_t : public Drul_array { static T infinity () ; static String T_to_str (T arg); - T center () { + T center () const { assert (!empty_b ()); return (elem (LEFT) + elem (RIGHT)) / T (2); } diff --git a/input/regression/accidental-placement.ly b/input/regression/accidental-placement.ly index 0b22b665e8..3653addaef 100644 --- a/input/regression/accidental-placement.ly +++ b/input/regression/accidental-placement.ly @@ -11,6 +11,7 @@ Accidentals in corresponding octaves are aligned." + } \paper { linewidth = -1. } } diff --git a/input/regression/completion-heads.ly b/input/regression/completion-heads.ly new file mode 100644 index 0000000000..6790220152 --- /dev/null +++ b/input/regression/completion-heads.ly @@ -0,0 +1,24 @@ +\version "1.5.50" + +\header{ +texidoc=" + +If the Note_heads_engraver is replaced by the Completion_heads_engraver, +notes that cross bar lines are split into tied notes. +" +} + +\score{ + \notes\relative c'{ + \time 2/4 + + c2. c8 d4 e f g a b c8 c2 b4 a g16 f4 e d c8. c2 + } + \paper{ + \translator{ + \ThreadContext + \remove "Note_heads_engraver" + \consists "Completion_heads_engraver" + } + } +} \ No newline at end of file diff --git a/input/regression/note-head-chord.ly b/input/regression/note-head-chord.ly new file mode 100644 index 0000000000..bfdd455cbd --- /dev/null +++ b/input/regression/note-head-chord.ly @@ -0,0 +1,16 @@ + +\header { + texidoc = "Note heads are flipped on the stem to prevent collisions. +It also works for whole heads that have invisible stems. +" + +} + +\score { \notes \relative c'' + \context Thread { + + + + + + }} diff --git a/lily/accidental-placement.cc b/lily/accidental-placement.cc index 5a8693b8ab..84e3c6c245 100644 --- a/lily/accidental-placement.cc +++ b/lily/accidental-placement.cc @@ -100,11 +100,27 @@ struct Accidental_placement_entry } }; +static Interval all_accidental_vertical_extent; +Real ape_priority (Accidental_placement_entry const * a) +{ + Real c = a->vertical_extent_.center(); + + /* + far from center means we can fold more. Hopefully. + */ + Real center_distance = + fabs(c - all_accidental_vertical_extent[LEFT]) >? + fabs(c - all_accidental_vertical_extent[RIGHT]); + + return 20 * a->vertical_extent_.length () + center_distance; +} + + int ape_compare (Accidental_placement_entry *const &a, Accidental_placement_entry *const &b) { - return sign (a->vertical_extent_.length () - b->vertical_extent_.length()); + return sign (ape_priority (a) - ape_priority(b)); } /* @@ -158,23 +174,20 @@ Accidental_placement::position_accidentals (Grob * me) Grob *commony =0 ; - for (int i= apes.size (); i--;) - commony = common_refpoint_of_array (apes[i]->grobs_, commony, Y_AXIS); + /* + First we must extract *all* pointers. We can only determine + extents if we're sure that we've found the right common refpoint + */ Link_array note_cols, heads; for (int i= apes.size (); i--;) - { + { 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--;) + for (int j = ape->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); - + Grob * a = ape->grobs_[j]; + + commony = commony->common_refpoint (a, Y_AXIS); Grob *head = a->get_parent (Y_AXIS); Grob * col = head->get_parent (X_AXIS); @@ -182,18 +195,8 @@ Accidental_placement::position_accidentals (Grob * me) note_cols.push (col); else heads.push (head); - - 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 = note_cols.size() ; i--;) { @@ -205,7 +208,34 @@ Accidental_placement::position_accidentals (Grob * me) heads.default_sort(); heads.uniq(); commony = common_refpoint_of_array (heads, commony, Y_AXIS); + + for (int i= apes.size (); i--;) + { + 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]; + Box b; + b[X_AXIS] = a->extent (me, X_AXIS); + b[Y_AXIS] = a->extent (commony, 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); + } + } + + + Interval total; for (int i = apes.size(); i--;) { Interval y ; @@ -215,8 +245,9 @@ Accidental_placement::position_accidentals (Grob * me) y.unite (apes[i]->extents_[j][Y_AXIS]); } apes[i]->vertical_extent_ = y; + total.unite (y); } - + all_accidental_vertical_extent = total; apes.sort (&ape_compare); Accidental_placement_entry * head_ape = new Accidental_placement_entry; @@ -244,20 +275,10 @@ Accidental_placement::position_accidentals (Grob * me) { Accidental_placement_entry *ape = apes[i]; 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); + apes[j]->left_skyline_); if (!isinf(d) || j + 1 == apes.size()) diff --git a/lily/auto-beam-engraver.cc b/lily/auto-beam-engraver.cc index 7c418a024b..5126db27db 100644 --- a/lily/auto-beam-engraver.cc +++ b/lily/auto-beam-engraver.cc @@ -370,7 +370,7 @@ Auto_beam_engraver::acknowledge_grob (Grob_info info) /* Don't (start) auto-beam over empty stems; skips or rests */ - if (!Stem::heads_i (stem_l)) + if (!Stem::head_count (stem_l)) { if (stem_l_arr_p_) end_beam (); diff --git a/lily/include/stem.hh b/lily/include/stem.hh index caa430cb42..1c3b90883c 100644 --- a/lily/include/stem.hh +++ b/lily/include/stem.hh @@ -33,7 +33,7 @@ public: static void set_stemend (Grob *,Real); static Direction get_default_dir (Grob *) ; - static int heads_i (Grob *) ; + static int head_count (Grob *) ; static bool invisible_b (Grob *) ; static Interval head_positions (Grob *) ; static Real get_default_stem_end_position (Grob*me) ; diff --git a/lily/skyline.cc b/lily/skyline.cc index cc47448ee9..9857fe4955 100644 --- a/lily/skyline.cc +++ b/lily/skyline.cc @@ -26,7 +26,7 @@ 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 diff --git a/lily/stem.cc b/lily/stem.cc index 0f6591987a..2b0874291e 100644 --- a/lily/stem.cc +++ b/lily/stem.cc @@ -56,7 +56,7 @@ Stem::beam_count (Grob*me,Direction d) Interval Stem::head_positions (Grob*me) { - if (!heads_i (me)) + if (!head_count (me)) { Interval iv; return iv; @@ -135,13 +135,13 @@ Stem::support_head (Grob*me) Grob * nh = unsmob_grob (h); if (nh) return nh; - else if (heads_i (me) == 1) + else if (head_count (me) == 1) { /* UGH. */ - return unsmob_grob (ly_car (me->get_grob_property ("heads"))); + return unsmob_grob (ly_car (me->get_grob_property ("note-heads"))); } else return first_head (me); @@ -149,9 +149,9 @@ Stem::support_head (Grob*me) int -Stem::heads_i (Grob*me) +Stem::head_count (Grob*me) { - return Pointer_group_interface::count (me, "heads"); + return Pointer_group_interface::count (me, "note-heads"); } /* @@ -177,7 +177,7 @@ Stem::extremal_heads (Grob*me) Drul_array exthead; exthead[LEFT] = exthead[RIGHT] =0; - for (SCM s = me->get_grob_property ("heads"); gh_pair_p (s); s = ly_cdr (s)) + for (SCM s = me->get_grob_property ("note-heads"); gh_pair_p (s); s = ly_cdr (s)) { Grob * n = unsmob_grob (ly_car (s)); @@ -207,7 +207,7 @@ Array Stem::note_head_positions (Grob *me) { Array ps ; - for (SCM s = me->get_grob_property ("heads"); gh_pair_p (s); s = ly_cdr (s)) + for (SCM s = me->get_grob_property ("note-heads"); gh_pair_p (s); s = ly_cdr (s)) { Grob * n = unsmob_grob (ly_car (s)); int p = int (Staff_symbol_referencer::position_f (n)); @@ -228,14 +228,14 @@ Stem::add_head (Grob*me, Grob *n) if (Note_head::has_interface (n)) { - Pointer_group_interface::add_grob (me, ly_symbol2scm ("heads"), n); + Pointer_group_interface::add_grob (me, ly_symbol2scm ("note-heads"), n); } } bool Stem::invisible_b (Grob*me) { - return ! (heads_i (me) && Rhythmic_head::balltype_i (support_head (me)) >= 1); + return ! (head_count (me) && Rhythmic_head::balltype_i (support_head (me)) >= 1); } Direction @@ -380,11 +380,11 @@ Stem::duration_log (Grob*me) void Stem::position_noteheads (Grob*me) { - if (!heads_i (me)) + if (!head_count (me)) return; Link_array heads = - Pointer_group_interface__extract_grobs (me, (Grob*)0, "heads"); + Pointer_group_interface__extract_grobs (me, (Grob*)0, "note-heads"); heads.sort (compare_position); Direction dir =get_direction (me); @@ -393,6 +393,13 @@ Stem::position_noteheads (Grob*me) heads.reverse (); + bool invisible = invisible_b (me); + Real thick = 0.0; + if (invisible) + thick = gh_scm2double (me->get_grob_property ("thickness")) + * me->paper_l ()->get_var ("linethickness"); + + Grob *hed = support_head (me); Real w = Note_head::head_extent (hed,X_AXIS)[dir]; for (int i=0; i < heads.size (); i++) @@ -414,7 +421,26 @@ Stem::position_noteheads (Grob*me) { Real l = Note_head::head_extent (heads[i], X_AXIS).length (); - heads[i]->translate_axis (l * get_direction (me), X_AXIS); + Direction d = get_direction (me); + heads[i]->translate_axis (l * d, X_AXIS); + + if (invisible_b(me)) + heads[i]->translate_axis (-thick *2* d , X_AXIS); + + + /* TODO: + + For some cases we should kern some more: when the + distance between the next or prev note is too large, we'd + get large white gaps, eg. + + | + X| + |X <- kern this. + | + X + + */ } parity = !parity; } @@ -431,7 +457,12 @@ Stem::before_line_breaking (SCM smob) { Grob*me = unsmob_grob (smob); - if (!invisible_b (me)) + + /* + Do the calculations for visible stems, but also for invisible stems + with note heads (i.e. half notes.) + */ + if (head_count (me)) { stem_end_position (me); // ugh. Trigger direction calc. position_noteheads (me); @@ -809,5 +840,5 @@ Stem::calc_stem_info (Grob*me) ADD_INTERFACE (Stem,"stem-interface", "A stem", - "adjust-if-on-staffline thickness stem-info beamed-lengths beamed-minimum-lengths lengths beam stem-shorten duration-log beaming neutral-direction stem-end-position support-head heads direction length style no-stem-extend flag-style dir-forced"); + "adjust-if-on-staffline thickness stem-info beamed-lengths beamed-minimum-lengths lengths beam stem-shorten duration-log beaming neutral-direction stem-end-position support-head note-heads direction length style no-stem-extend flag-style dir-forced"); diff --git a/mf/feta-nummer16.mf b/mf/feta-nummer16.mf new file mode 100644 index 0000000000..92423b0058 --- /dev/null +++ b/mf/feta-nummer16.mf @@ -0,0 +1,2 @@ +design_size := 16; +input feta-nummer; diff --git a/mf/feta-nummer20.mf b/mf/feta-nummer20.mf new file mode 100644 index 0000000000..8ddfd9e16a --- /dev/null +++ b/mf/feta-nummer20.mf @@ -0,0 +1,2 @@ +design_size := 20.74; +input feta-nummer; diff --git a/mf/feta-nummer23.mf b/mf/feta-nummer23.mf new file mode 100644 index 0000000000..d3241514f3 --- /dev/null +++ b/mf/feta-nummer23.mf @@ -0,0 +1,2 @@ +design_size := 23; +input feta-nummer; diff --git a/mf/feta-nummer26.mf b/mf/feta-nummer26.mf new file mode 100644 index 0000000000..a9308dd0ba --- /dev/null +++ b/mf/feta-nummer26.mf @@ -0,0 +1,2 @@ +design_size := 26; +input feta-nummer; diff --git a/scm/grob-property-description.scm b/scm/grob-property-description.scm index 6eb69c3ac0..e226f9082e 100644 --- a/scm/grob-property-description.scm +++ b/scm/grob-property-description.scm @@ -188,11 +188,7 @@ is used by @ref{note-collision-interface}.") (grob-property-description 'grow-direction dir? "crescendo or decrescendo?.") (grob-property-description 'hair-thickness number? "thickness, measured in stafflinethickness.") -(grob-property-description 'heads pair? "list of note heads, - -FIXME: in Tie this is a pair of grob pointers, pointing to the two heads of the tie. - -.") +(grob-property-description 'heads pair? "Pair of grob pointers, pointing to the two heads of the tie.") (grob-property-description 'height number? "in staffspace.") (grob-property-description 'horizontal-shift integer? "integer that identifies ranking of note-column for horizontal shifting. This is used by @ref{note-collision-interface}.") (grob-property-description 'ideal-distances list? "(OBJ . (DIST . STRENGTH)) pairs.") diff --git a/scripts/lilypond-book.py b/scripts/lilypond-book.py index 9710a8dcc0..4cab883e7a 100644 --- a/scripts/lilypond-book.py +++ b/scripts/lilypond-book.py @@ -836,7 +836,7 @@ def chop_chunks(chunks, re_name, func, use_match=0): if c[0] == 'input': str = c[1] while str: - print re_name +# print re_name m = get_re (re_name).search (str) if m == None: newchunks.append (('input', str)) -- 2.39.2