From: Han-Wen Nienhuys Date: Wed, 13 Mar 2002 00:19:52 +0000 (+0100) Subject: release: 1.5.39 X-Git-Tag: release/1.5.39 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=401b95daacfd7b516ceb776b6204f6851da3cd95;p=lilypond.git release: 1.5.39 --- diff --git a/ChangeLog b/ChangeLog index 8d867f846f..f0c2a013f2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,49 +1,67 @@ ---- ../lilypond-1.5.38.jcn1/ChangeLog Mon Mar 11 19:49:41 2002 -++ b/ChangeLog Tue Mar 12 21:20:33 2002 -@@ -1,4 +1,21 @@ +2002-03-13 Han-Wen + + * VERSION: 1.5.39 released + + * lily/simple-spacer.cc (add_rod): rods take precedence over + infinitely stiff springs. This fixes bugs with arpeggios and bar-lines. + + * lily/arpeggio-engraver.cc (acknowledge_grob): clean up. + + * lily/note-spacing.cc (get_spacing): only insert space for + accidentals if necessary. + + * input/regression/spacing-accidental-staffs.ly (texidoc): update example + + * lily/spacing-spanner.cc (musical_column_spacing): new + function. Have correct spacing from note to end-of-line as well. + 2002-03-12 Jan Nieuwenhuizen - * Documentation/topdocs/INSTALL.texi: Add section for MacOS X. + * Documentation/topdocs/INSTALL.texi: Add section for MacOS X. - * darwin.patch: New file. + * darwin.patch: New file. - * lily/beam.cc (set_stem_shorten): Revive deceased stem shorten - code. Shorten stems by fraction of stems to be shortened. + * lily/beam.cc (set_stem_shorten): Revive deceased stem shorten + code. Shorten stems by fraction of stems to be shortened. - * lily/stem.cc (get_default_stem_end_position): Shorten only half - of shorten value for boundary cases. + * lily/stem.cc (get_default_stem_end_position): Shorten only half + of shorten value for boundary cases. - * scm/grob-description.scm (Stem): Set stem-shorten to (1.0 0.5). - (Beam): Set beamed-stem-shorten to (1.0 0.5). + * scm/grob-description.scm (Stem): Set stem-shorten to (1.0 0.5). + (Beam): Set beamed-stem-shorten to (1.0 0.5). - 2002-03-11 Jan Nieuwenhuizen +2002-03-11 Jan Nieuwenhuizen - * lily/beam.cc (check_stem_length_f): Try to lenthen more. + * lily/beam.cc (check_stem_length_f): Try to lenthen more. + + * scm/grob-description.scm (Beam): Add concaveness. Replace + Beam::cancel_suspect_slope with Beam::check_concave. - * scm/grob-description.scm (Beam): Add concaveness. Replace - Beam::cancel_suspect_slope with Beam::check_concave.--- ../lilypond-1.5.38.chj1/ChangeLog Tue Mar 12 01:43:11 2002 -++ b/ChangeLog Tue Mar 12 01:40:48 2002 -@@ -1,3 +1,8 @@ + * lily/beam.cc (check_concave): Calculate concaveness of beam, and + set slope to horizontal if concaveness > Beam.concaveness. This + handles cases that kludgy cancel_suspect_slope was meant to catch + very well. + (cancel_suspect_slope): Remove. + 2002-03-12 Rune Zedeler - * lily/beam.cc lily/stem.cc lily/beam-engraver.cc allow for - stemLeftBeamCount and stemRightBeamCount to equal 0. - Fixes [c8 c4 c8] - 2002-03-07 Chris Jackson - - * lily/piano-pedal-engraver.cc Rewritten to support bracketed as2002-03-11 Jan Nieuwenhuizen + * lily/beam.cc lily/stem.cc lily/beam-engraver.cc allow for + stemLeftBeamCount and stemRightBeamCount to equal 0. + Fixes [c8 c4 c8] + +2002-03-12 Han-Wen - * scm/grob-description.scm (Beam): Add concaveness. Replace - Beam::cancel_suspect_slope with Beam::check_concave. + * lily/spacing-spanner.cc (breakable_column_spacing): Only do + fixed spacing for pref matter, if the next column is musical, and + at the same moment. + + * lily/note-spacing.cc (stem_dir_correction): Use correct + discretionary for stem-bar spacing. - * lily/beam.cc (check_concave): Calculate concaveness of beam, and - set slope to horizontal if concaveness > Beam.concaveness. This - handles cases that kludgy cancel_suspect_slope was meant to catch - very well. - (cancel_suspect_slope): Remove. - 2002-03-11 Han-Wen + * VERSION: 1.5.38 released + * lily/grob.cc (warning): Use cause tracking to give more meaningful errors from the backend. diff --git a/INSTALL.txt b/INSTALL.txt index 8f5223850c..ff40bb05c6 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -25,6 +25,7 @@ INSTALL - compiling and installing GNU LilyPond Slackware Mandrake Debian GNU/Linux + MacOS X Problems FLex-2.5.4a and gcc-3.0 Python-2.1[.1] @@ -486,6 +487,40 @@ interfere with your build, you may want to do this before the build too: dpkg --purge lilypond lilypond1.3 +MacOS X +------- + + LilyPond has been built on Darwin, to be precise, on: + Darwin buoux.aspiratie.nl 5.3 Darwin Kernel Version 5.3: Thu Jan 24 + 22:06:02 PST 2002; root:xnu/xnu-201.19.obj~1/RELEASE_PPC Power Macintosh powerpc + + using: + + Apple Computer, Inc. version gcc-932.1, based on gcc version 2.95.2 19991024 (release) + + To make sure you have all packages needed to build LilyPond +installed, run as root: + + apt-get install bash python guile debianutils flex bison texinfo \ + ghostscript6 netpbm m4 gettext + + and: + + fink install tetex + + Then, configure, patch, make and install LilyPond using these +commands: + + CC="cc -I/sw/include" CXX="c++ -I/sw/include" LDFLAGS="-L/sw/lib" \ + ./configure --prefix=/sw + make -C lily out/parser.hh out/parser.cc + patch -p0 < darwin.patch + make -C lily out/parser.o + make all + make install + + For installing, you must be root, of course. + Problems ======== diff --git a/VERSION b/VERSION index f20360b40c..c8347e6d4b 100644 --- a/VERSION +++ b/VERSION @@ -1,8 +1,8 @@ PACKAGE_NAME=LilyPond MAJOR_VERSION=1 MINOR_VERSION=5 -PATCH_LEVEL=38 -MY_PATCH_LEVEL=jcn2 +PATCH_LEVEL=39 +MY_PATCH_LEVEL= # use the above to send patches: MY_PATCH_LEVEL is always empty for a # released version. diff --git a/input/GNUmakefile b/input/GNUmakefile index 9cf5f1fd68..30e35d85d1 100644 --- a/input/GNUmakefile +++ b/input/GNUmakefile @@ -3,7 +3,7 @@ depth = .. SUBDIRS=bugs test regression tutorial no-notation ascii-art template # nereides is tweaked a lot, can't do (read webpage) -examples=trip star-spangled-banner paddy twinkle #nereides +examples=trip star-spangled-banner paddy twinkle baerenreiter-sarabande #nereides LOCALSTEPMAKE_TEMPLATES=ly mutopia EXTRA_DIST_FILES=paddy.abc diff --git a/input/baerenreiter-sarabande.ly b/input/baerenreiter-sarabande.ly index f1ab03568e..2c4e0835b8 100644 --- a/input/baerenreiter-sarabande.ly +++ b/input/baerenreiter-sarabande.ly @@ -16,8 +16,15 @@ benchmarkk the quality of the LilyPond output. As of lilypond 1.5.38, the spacing is almost identical. With a line-break forced before measure 25, we get back the linebreaking of Baerenreiter. + + This file used to show spacing weaknesses. Now it shows weaknesses in -beam and slur handling." +beam and slur handling. + +Note that the Barenreiter edition contains an engraving mistake. The +second line begins with measure 6 (but prints 5). + +" } @@ -27,9 +34,6 @@ beam and slur handling." sarabandeA = \context Voice \notes \relative c { \property Staff.NoteCollision \set #'merge-differently-dotted = ##t - \property Voice.Beam \set #'quantise-dy-never-steeper = ##t - \property Voice.Beam \set #'ideal-lengthen = ##t - < { d8. e16 e4.-\trill d16 e } \\ { d4 a2 } > f4. [e8 d c] | @@ -95,9 +99,8 @@ sarabandeA = \context Voice \notes \relative c { gis4. } > \stemUp d16(cis)d f, - [a,8 e'] \stemBoth - [d' cis] | + [a,8 e'] [d' cis] | d4 d,,2 | } diff --git a/input/bugs/sammartini.ly b/input/bugs/sammartini.ly new file mode 100644 index 0000000000..e77ad1fe17 --- /dev/null +++ b/input/bugs/sammartini.ly @@ -0,0 +1,65 @@ + +% +% bug: 1st tuplet spacing weird. + +\include "paper16.ly" + +stemDown = \property Voice.Stem \override #'direction = #-1 +stemUp = \property Voice.Stem \override #'direction = #1 +stemBoth = \property Voice.Stem \revert #'direction + +viola = \notes \relative c' \context Voice = viola { + + \stemDown g'8. b,16 + s1 s2. r4 + g +} + +oboes = \notes \relative c'' \context Voice = oboe { + \stemUp s4 g8. b,16 c8 r + \grace + \times 2/3 { } + < + { \times 2/3 { a8 g c } \! c2 } + \context Voice = oboeTwo { + \stemDown + \grace { + \stemDown + [f,16 g] } + f8 e e2 + } + > + \stemBoth + \grace <)b8. d8.-\trill> | + [ < )f8. a>] <)b,8 d> r [ ] r | + [ < )e8. g>] +} + +hoomPah = \repeat unfold 8 \notes + \transpose c' { c8 \stemDown c'8 \stemUp } + +bassvoices = \notes \relative c' { + c4 g8. b,16 + \autochange Staff \hoomPah + \translator Staff = down + \stemDown [c8 c'8] r4 + r4 + < {\stemUp r2 } + \context Voice = reallyLow {\stemDown g2 ~ | g4 c8 } > +} + +\score { + \context PianoStaff \notes < + \context Staff = up < \time 2/2 + \viola + \oboes + > + \context Staff = down < \time 2/2 \clef bass + \bassvoices + > + > + \midi { } + \paper { + indent = 0.0 + linewidth = 15.0 \cm } +} diff --git a/input/regression/spacing-accidental-staffs.ly b/input/regression/spacing-accidental-staffs.ly index 175be7bade..848579c9a2 100644 --- a/input/regression/spacing-accidental-staffs.ly +++ b/input/regression/spacing-accidental-staffs.ly @@ -4,14 +4,14 @@ texidoc = "Accidentals in different staffs don't effect the spacing of the quarter notes here." } -\score { \notes \relative c'' < \context Staff = SA { \time 8/4 +\score { \notes \relative c'' < \context Staff = SA { \time 4/4 -c4 c4 cis4 cis4 -cis4 cis4 cis4 cis +[c8 c8 cis8 cis8] +[cis8 cis8 cis8 cis] } - { \key d \major cis2 cis2 cis2 cis!2 } > + { \key d \major cis4 cis4 cis4 cis!4 } > \paper { linewidth = -1. } } diff --git a/input/regression/spacing-accidental.ly b/input/regression/spacing-accidental.ly index f138c3865d..5afe8286af 100644 --- a/input/regression/spacing-accidental.ly +++ b/input/regression/spacing-accidental.ly @@ -1,10 +1,13 @@ \header { texidoc = "Accidentals sticking out to the left -of a note will take a little more space." +of a note will take a little more space, but only if the spacing is tight." } -\score { \notes \relative c'' { c4 c cis4 +\score { \notes \relative c'' { + \time 8/4 + c2 c2 cis2 cis2 | + c8 c8 cis8 cis8 cis c c c] } \paper { linewidth = -1. } diff --git a/lily/arpeggio-engraver.cc b/lily/arpeggio-engraver.cc index b236e8b8d8..8aee3f9397 100644 --- a/lily/arpeggio-engraver.cc +++ b/lily/arpeggio-engraver.cc @@ -12,10 +12,9 @@ #include "musical-request.hh" #include "arpeggio.hh" #include "stem.hh" -#include "local-key-item.hh" #include "rhythmic-head.hh" #include "side-position-interface.hh" -#include "staff-symbol-referencer.hh" +#include "note-column.hh" class Arpeggio_engraver : public Engraver { @@ -23,15 +22,14 @@ public: TRANSLATOR_DECLARATIONS(Arpeggio_engraver); protected: virtual void acknowledge_grob (Grob_info); - virtual void create_grobs (); + virtual void process_music (); + virtual void stop_translation_timestep (); virtual bool try_music (Music *); private: Item* arpeggio_; Arpeggio_req *arpeggio_req_; - Link_array stems_; - Link_array supports_; }; Arpeggio_engraver::Arpeggio_engraver () @@ -57,11 +55,14 @@ Arpeggio_engraver::try_music (Music* m) void Arpeggio_engraver::acknowledge_grob (Grob_info info) { - if (arpeggio_req_) + if (arpeggio_) { if (Stem::has_interface (info.grob_l_)) { - stems_.push (info.grob_l_); + if (!arpeggio_->get_parent (Y_AXIS)) + arpeggio_->set_parent (info.grob_l_, Y_AXIS); + + Pointer_group_interface::add_grob (arpeggio_, ly_symbol2scm ("stems"), info.grob_l_); } /* @@ -70,27 +71,21 @@ Arpeggio_engraver::acknowledge_grob (Grob_info info) */ else if (Rhythmic_head::has_interface (info.grob_l_)) { - supports_.push (info.grob_l_); + Side_position_interface::add_support (arpeggio_, info.grob_l_); + } + else if (Note_column::has_interface (info.grob_l_ )) + { + info.grob_l_->set_grob_property ("arpeggio", arpeggio_->self_scm ()); } } } void -Arpeggio_engraver::create_grobs () +Arpeggio_engraver::process_music () { - if (!arpeggio_ && !stems_.empty ()) + if (arpeggio_req_) { arpeggio_ = new Item (get_property ("Arpeggio")); - arpeggio_->set_parent (stems_[0], Y_AXIS); - - for (int i = 0; i < stems_.size (); i++) - { - Pointer_group_interface::add_grob (arpeggio_, ly_symbol2scm ("stems"), stems_[i]); - } - for (int i = 0; i < supports_.size (); i++) - { - Side_position_interface::add_support (arpeggio_, supports_[i]); - } announce_grob(arpeggio_, arpeggio_req_->self_scm()); } } @@ -104,8 +99,6 @@ Arpeggio_engraver::stop_translation_timestep () arpeggio_ = 0; } arpeggio_req_ = 0; - stems_.clear (); - supports_.clear (); } @@ -114,6 +107,6 @@ Arpeggio_engraver::stop_translation_timestep () ENTER_DESCRIPTION(Arpeggio_engraver, /* descr */ "Generate an Arpeggio from a Arpeggio_req", /* creats*/ "Arpeggio", -/* acks */ "stem-interface rhythmic-head-interface", +/* acks */ "stem-interface rhythmic-head-interface note-column-interface", /* reads */ "", /* write */ ""); diff --git a/lily/beam.cc.orig b/lily/beam.cc.orig deleted file mode 100644 index 11b2c312b6..0000000000 --- a/lily/beam.cc.orig +++ /dev/null @@ -1,1207 +0,0 @@ -/* - beam.cc -- implement Beam - - source file of the GNU LilyPond music typesetter - - (c) 1997--2002 Han-Wen Nienhuys - Jan Nieuwenhuizen - -*/ - -/* - [TODO] - - -* shorter! (now +- 1000 lines) - - -* less hairy code - - -* Remove #'direction from beam. The beam has no direction per se. - It may only set directions for stems. - */ - - -#include // tanh. - -#include "molecule.hh" -#include "directional-element-interface.hh" -#include "beaming.hh" -#include "beam.hh" -#include "misc.hh" -#include "least-squares.hh" -#include "stem.hh" -#include "paper-def.hh" -#include "lookup.hh" -#include "group-interface.hh" -#include "staff-symbol-referencer.hh" -#include "item.hh" -#include "spanner.hh" -#include "warn.hh" - -void -Beam::add_stem (Grob*me, Grob*s) -{ - Pointer_group_interface::add_grob (me, ly_symbol2scm ("stems"), s); - - s->add_dependency (me); - - assert (!Stem::beam_l (s)); - s->set_grob_property ("beam", me->self_scm ()); - - add_bound_item (dynamic_cast (me), dynamic_cast (s)); -} - -int -Beam::get_multiplicity (Grob*me) -{ - int m = 0; - for (SCM s = me->get_grob_property ("stems"); gh_pair_p (s); s = ly_cdr (s)) - { - Grob * sc = unsmob_grob (ly_car (s)); - - if (Stem::has_interface (sc)) - m = m >? Stem::beam_count (sc,LEFT) >? Stem::beam_count (sc,RIGHT); - } - return m; -} - -/* - After pre-processing all directions should be set. - Several post-processing routines (stem, slur, script) need stem/beam - direction. - Currenly, this means that beam has set all stem's directions. - [Alternatively, stems could set its own directions, according to - their beam, during 'final-pre-processing'.] - */ -MAKE_SCHEME_CALLBACK (Beam,before_line_breaking,1); -SCM -Beam::before_line_breaking (SCM smob) -{ - Grob * me = unsmob_grob (smob); - - /* - Beams with less than 2 two stems don't make much sense, but could happen - when you do - - [r8 c8 r8]. - - For a beam that only has one stem, we try to do some disappearance magic: - we revert the flag, and move on to The Eternal Engraving Fields.*/ - - - if (visible_stem_count (me) < 2) - { - me->warning (_ ("beam has less than two visible stems")); - - SCM stems = me->get_grob_property ("stems"); - if (scm_ilength (stems) == 1) - { - me->warning (_("Beam has less than two stems. Removing beam.")); - - unsmob_grob (gh_car (stems))->remove_grob_property ("beam"); - me->suicide (); - - return SCM_UNSPECIFIED; - } - else if (scm_ilength (stems) == 0) - { - me->suicide (); - return SCM_UNSPECIFIED; - } - } - if (visible_stem_count (me) >= 1) - { - if (!Directional_element_interface::get (me)) - Directional_element_interface::set (me, get_default_dir (me)); - - consider_auto_knees (me); - set_stem_directions (me); - set_stem_shorten (me); - } - return SCM_EOL; -} - -Direction -Beam::get_default_dir (Grob*me) -{ - Drul_array total; - total[UP] = total[DOWN] = 0; - Drul_array count; - count[UP] = count[DOWN] = 0; - Direction d = DOWN; - - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); - - for (int i=0; i get_grob_property ("dir-function"); - SCM s = gh_call2 (func, - gh_cons (gh_int2scm (count[UP]), - gh_int2scm (count[DOWN])), - gh_cons (gh_int2scm (total[UP]), - gh_int2scm (total[DOWN]))); - - if (gh_number_p (s) && gh_scm2int (s)) - return to_dir (s); - - /* - If dir is not determined: get default - */ - return to_dir (me->get_grob_property ("neutral-direction")); -} - - -/* - Set all stems with non-forced direction to beam direction. - Urg: non-forced should become `without/with unforced' direction, - once stem gets cleaned-up. - */ -void -Beam::set_stem_directions (Grob*me) -{ - Link_array stems - =Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); - Direction d = Directional_element_interface::get (me); - - for (int i=0; i remove_grob_property ("dir-forced"); - if (!gh_boolean_p (force) || !gh_scm2bool (force)) - Directional_element_interface ::set (s,d); - } -} - -/* - Simplistic auto-knees; only consider vertical gap between two - adjacent chords. - - `Forced' stem directions are ignored. If you don't want auto-knees, - don't set, or unset auto-knee-gap. - */ -void -Beam::consider_auto_knees (Grob *me) -{ - SCM scm = me->get_grob_property ("auto-knee-gap"); - - if (gh_number_p (scm)) - { - bool knee_b = false; - Real knee_y = 0; - Real staff_space = Staff_symbol_referencer::staff_space (me); - Real gap = gh_scm2double (scm) / staff_space; - - Direction d = Directional_element_interface::get (me); - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); - - Grob *common = me->common_refpoint (stems[0], Y_AXIS); - for (int i=1; i < stems.size (); i++) - if (!Stem::invisible_b (stems[i])) - common = common->common_refpoint (stems[i], Y_AXIS); - - int l = 0; - for (int i=1; i < stems.size (); i++) - { - if (!Stem::invisible_b (stems[i-1])) - l = i - 1; - if (Stem::invisible_b (stems[l])) - continue; - if (Stem::invisible_b (stems[i])) - continue; - - Real left = Stem::extremal_heads (stems[l])[d] - ->relative_coordinate (common, Y_AXIS); - Real right = Stem::extremal_heads (stems[i])[-d] - ->relative_coordinate (common, Y_AXIS); - - Real dy = right - left; - - if (abs (dy) >= gap) - { - knee_y = (right + left) / 2; - knee_b = true; - break; - } - } - - if (knee_b) - { - for (int i=0; i < stems.size (); i++) - { - if (Stem::invisible_b (stems[i])) - continue; - Item *s = stems[i]; - Real y = Stem::extremal_heads (stems[i])[d] - ->relative_coordinate (common, Y_AXIS); - - Directional_element_interface::set (s, y < knee_y ? UP : DOWN); - s->set_grob_property ("dir-forced", SCM_BOOL_T); - } - } - } -} - -/* - Set stem's shorten property if unset. - TODO: - take some y-position (chord/beam/nearest?) into account - scmify forced-fraction - */ -void -Beam::set_stem_shorten (Grob*m) -{ - Spanner*me = dynamic_cast (m); - - Real forced_fraction = forced_stem_count (me) / visible_stem_count (me); - if (forced_fraction < 0.5) - return; - - int multiplicity = get_multiplicity (me); - - SCM shorten = me->get_grob_property ("beamed-stem-shorten"); - if (shorten == SCM_EOL) - return; - - int sz = scm_ilength (shorten); - - Real staff_space = Staff_symbol_referencer::staff_space (me); - SCM shorten_elt = scm_list_ref (shorten, gh_int2scm (multiplicity stems= - Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); - - for (int i=0; i < stems.size (); i++) - { - Item* s = stems[i]; - if (Stem::invisible_b (s)) - continue; - if (gh_number_p (s->get_grob_property ("shorten"))) - s->set_grob_property ("shorten", gh_double2scm (shorten_f)); - } -} - -/* - Call list of y-dy-callbacks, that handle setting of - grob-properties y, dy. - - User may set grob-properties: y-position-hs and height-hs - (to be fixed) that override the calculated y and dy. - - Because y and dy cannot be calculated and quanted separately, we - always calculate both, then check for user override. - */ -MAKE_SCHEME_CALLBACK (Beam, after_line_breaking, 1); -SCM -Beam::after_line_breaking (SCM smob) -{ - Grob * me = unsmob_grob (smob); - - me->set_grob_property ("y", gh_double2scm (0)); - me->set_grob_property ("dy", gh_double2scm (0)); - - /* Hmm, callbacks should be called by, a eh, callback mechanism - somewhere (?), I guess, not by looping here. */ - - SCM list = me->get_grob_property ("y-dy-callbacks"); - for (SCM i = list; gh_pair_p (i); i = ly_cdr (i)) - gh_call1 (ly_car (i), smob); - - // UGH. Y is not in staff position unit? - // Ik dacht datwe daar juist van weg wilden? - - // Hmm, nu hebben we 3 dimensies, want inmiddels zijn we daar - // weer terug, maar dan / 2 - // (staff-space iso staff-position) - - set_stem_lengths (me); - - return SCM_UNSPECIFIED; -} - - -MAKE_SCHEME_CALLBACK (Beam, least_squares, 1); -SCM -Beam::least_squares (SCM smob) -{ - Grob *me = unsmob_grob (smob); - - if (visible_stem_count (me) <= 1) - return SCM_UNSPECIFIED; - - Real y = 0; - Real dy = 0; - - /* Stem_info, and thus y,dy in this function are corrected for beam-dir */ - Real first_ideal = Stem::calc_stem_info (first_visible_stem (me)).idealy_f_; - if (first_ideal == Stem::calc_stem_info (last_visible_stem (me)).idealy_f_) - { - y = first_ideal; - dy = 0; - } - else - { - Array ideals; - - // ugh -> use commonx - Real x0 = first_visible_stem (me)->relative_coordinate (0, X_AXIS); - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); - - for (int i=0; i < stems.size (); i++) - { - Item* s = stems[i]; - if (Stem::invisible_b (s)) - continue; - ideals.push (Offset (s->relative_coordinate (0, X_AXIS) - x0, - Stem::calc_stem_info (s).idealy_f_)); - } - Real dydx; - minimise_least_squares (&dydx, &y, ideals); - - Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - x0; - dy = dydx * dx; - } - - /* Store true, not dir-corrected values */ - Direction dir = Directional_element_interface::get (me); - me->set_grob_property ("y", gh_double2scm (y * dir)); - me->set_grob_property ("dy", gh_double2scm (dy * dir)); - return SCM_UNSPECIFIED; -} - -#include -MAKE_SCHEME_CALLBACK (Beam, check_concave, 1); -SCM -Beam::check_concave (SCM smob) -{ - Grob *me = unsmob_grob (smob); - - Link_array stems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); - - for (int i = 0; i < stems.size ();) - { - if (Stem::invisible_b (stems[i])) - stems.del (i); - else - i++; - } - - if (stems.size () < 3) - return SCM_UNSPECIFIED; - - SCM s = me->get_grob_property ("concaveness-no-slope"); - - Real concave = 0; - if (!to_boolean (s)) - { - /* Concaveness try #1: Sum distances of inner noteheads to line - between two outer noteheads. */ - - Real dy = Stem::chord_start_f (stems.top ()) - - Stem::chord_start_f (stems[0]); - Real slope = dy / (stems.size () - 1); - - Real y0 = Stem::chord_start_f (stems[0]); - for (int i = 1; i < stems.size () - 1; i++) - { - Real c = (Stem::chord_start_f (stems[i]) - y0) - i * slope; - concave += c; - } - - } - else - { - /* Concaveness try #2: Sum distances of inner noteheads that - fall outside the interval of the two outer noteheads */ - - Interval iv = Interval (Stem::chord_start_f (stems[0]), - Stem::chord_start_f (stems.top ())); - - if (iv[MAX] < iv[MIN]) - // iv.swap (); - iv = Interval (iv[MAX], iv[MIN]); - - for (int i = 1; i < stems.size () - 1; i++) - { - Real c = 0; - Real f = Stem::chord_start_f (stems[i]); - if ((c = f - iv[MAX]) > 0) - concave += c; - else if ((c = f - iv[MIN]) < 0) - concave += c; - } - } - - concave *= Directional_element_interface::get (me); - - Real concaveness = concave / (stems.size () - 2); - - /* ugh: this is the a kludge to get input/regression/beam-concave.ly - to behave as baerenreiter. */ - s = me->get_grob_property ("concaveness-square"); - if (to_boolean (s)) - concaveness /= (stems.size () - 2); - - s = me->get_grob_property ("concaveness"); - Real r = gh_scm2double (s); - - if (concaveness > r) - { - Direction dir = Directional_element_interface::get (me); - Real y = gh_scm2double (me->get_grob_property ("y")) * dir; - Real dy = gh_scm2double (me->get_grob_property ("dy")) * dir; - - Real adjusted_y = y + dy / 2; - /* Store true, not dir-corrected values */ - me->set_grob_property ("y", gh_double2scm (adjusted_y * dir)); - me->set_grob_property ("dy", gh_double2scm (0)); - } - - s = me->get_grob_property ("debug-concave"); - if (to_boolean (s)) - { -#if 0 - Item *text = new Item (me->get_property ("TextScript")); - text->set_grob_property ("text", - ly_str02scm (to_str (concaveness).ch_C ())), - Side_position_interface::add_support (text, stem[0]); -#else - printf ("concaveness: %.2f\n", concaveness); -#endif - } - - return SCM_UNSPECIFIED; -} - -/* - This neat trick is by Werner Lemberg, - damped = tanh (slope) - corresponds with some tables in [Wanske] -*/ -MAKE_SCHEME_CALLBACK (Beam, slope_damping, 1); -SCM -Beam::slope_damping (SCM smob) -{ - Grob *me = unsmob_grob (smob); - - if (visible_stem_count (me) <= 1) - return SCM_UNSPECIFIED; - - SCM s = me->get_grob_property ("damping"); - int damping = gh_scm2int (s); - - if (damping) - { - /* y,dy in this function are corrected for beam-dir */ - Direction dir = Directional_element_interface::get (me); - Real y = gh_scm2double (me->get_grob_property ("y")) * dir; - Real dy = gh_scm2double (me->get_grob_property ("dy")) * dir; - - // ugh -> use commonx - Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - - first_visible_stem (me)->relative_coordinate (0, X_AXIS); - Real dydx = dy && dx ? dy/dx : 0; - dydx = 0.6 * tanh (dydx) / damping; - - Real damped_dy = dydx * dx; - Real adjusted_y = y + (dy - damped_dy) / 2; - /* Store true, not dir-corrected values */ - me->set_grob_property ("y", gh_double2scm (adjusted_y * dir)); - me->set_grob_property ("dy", gh_double2scm (damped_dy * dir)); - } - return SCM_UNSPECIFIED; -} - -/* - Quantise dy (height) of beam. - Generalisation of [Ross]. - */ -MAKE_SCHEME_CALLBACK (Beam, quantise_dy, 1); -SCM -Beam::quantise_dy (SCM smob) -{ - Grob *me = unsmob_grob (smob); - - if (visible_stem_count (me) <= 1) - return SCM_UNSPECIFIED; - - Array a; - SCM proc = me->get_grob_property ("height-quants"); - SCM quants = gh_call2 (proc, me->self_scm (), - gh_double2scm (me->paper_l ()->get_var ("stafflinethickness") - / 1.0)); - - for (SCM s = quants; gh_pair_p (s); s = ly_cdr (s)) - a.push (gh_scm2double (ly_car (s))); - - if (a.size () > 1) - { - /* y,dy in this function are corrected for beam-dir */ - Direction dir = Directional_element_interface::get (me); - Real y = gh_scm2double (me->get_grob_property ("y")) * dir; - Real dy = gh_scm2double (me->get_grob_property ("dy")) * dir; - - Real staff_space = Staff_symbol_referencer::staff_space (me); - - Interval iv = quantise_iv (a, abs (dy)/staff_space) * staff_space; - Real q = (abs (dy) - iv[SMALLER] <= iv[BIGGER] - abs (dy)) - ? iv[SMALLER] - : iv[BIGGER]; - - Real quantised_dy = q * sign (dy); - Real adjusted_y = y + (dy - quantised_dy) / 2; - /* Store true, not dir-corrected values */ - me->set_grob_property ("y", gh_double2scm (adjusted_y * dir)); - me->set_grob_property ("dy", gh_double2scm (quantised_dy * dir)); - } - return SCM_UNSPECIFIED; -} - -/* It's tricky to have the user override y,dy directly, so we use this - translation func. Also, if our staff_space != 1 (smaller staff, eg), - user will expect staff-position to be discrete values. */ -MAKE_SCHEME_CALLBACK (Beam, user_override, 1); -SCM -Beam::user_override (SCM smob) -{ - Grob *me = unsmob_grob (smob); - Real staff_space = Staff_symbol_referencer::staff_space (me); - - SCM s = me->get_grob_property ("staff-position"); - if (gh_number_p (s)) - { - Real y = gh_scm2double (s) * staff_space * 0.5; - me->set_grob_property ("y", gh_double2scm (y)); - } - - /* Name suggestions? Tilt, slope, vertical-* ? */ - s = me->get_grob_property ("height"); - if (gh_number_p (s)) - { - Real dy = gh_scm2double (s) * staff_space * 0.5; - me->set_grob_property ("dy", gh_double2scm (dy)); - } - - return SCM_UNSPECIFIED; -} - -/* - Ugh, this must be last, after user_override - Assumes directionised y/dy. - */ -MAKE_SCHEME_CALLBACK (Beam, do_quantise_y, 1); -SCM -Beam::do_quantise_y (SCM smob) -{ - Grob *me = unsmob_grob (smob); - - /* - If the user set y-position, we shouldn't do quanting. - */ - if (gh_number_p (me->get_grob_property ("y-position-hs"))) - return SCM_UNSPECIFIED; - - Real y = gh_scm2double (me->get_grob_property ("y")); - Real dy = gh_scm2double (me->get_grob_property ("dy")); - - /* we can modify y, so we should quantise y */ - Real half_space = Staff_symbol_referencer::staff_space (me) / 2; - Real y_shift = check_stem_length_f (me, y, dy); - y += y_shift; - y = quantise_y_f (me, y, dy, 0); - - /* - Hmm, this is a bit keyhole operation: we're passing `this' as a - parameter, and member vars as SCM properties. We should decide on - SCM/C/C++ boundary */ - me->set_grob_property ("y", gh_double2scm (y)); - set_stem_lengths (me); - y = gh_scm2double (me->get_grob_property ("y")); - - y_shift = check_stem_length_f (me, y, dy); - - if (y_shift > half_space / 4) - { - y += y_shift; - - /* - for significantly lengthened or shortened stems, - request quanting the other way. - */ - int quant_dir = 0; - if (abs (y_shift) > half_space / 2) - quant_dir = sign (y_shift) * Directional_element_interface::get (me); - y = quantise_y_f (me, y, dy, quant_dir); - } - - me->set_grob_property ("y", gh_double2scm (y)); - // me->set_grob_property ("dy", gh_double2scm (dy)); - return SCM_UNSPECIFIED; -} - - -Real -Beam::calc_stem_y_f (Grob*me,Item* s, Real y, Real dy) -{ - int beam_multiplicity = get_multiplicity (me); - int stem_multiplicity = (Stem::flag_i (s) - 2) >? 0; - - SCM space_proc = me->get_grob_property ("space-function"); - SCM space = gh_call1 (space_proc, gh_int2scm (beam_multiplicity)); - - Real thick = gh_scm2double (me->get_grob_property ("thickness")) ; - Real interbeam_f = gh_scm2double (space) ; - - // ugh -> use commonx - Real x0 = first_visible_stem (me)->relative_coordinate (0, X_AXIS); - Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - x0; - Real stem_y = (dy && dx ? (s->relative_coordinate (0, X_AXIS) - x0) / dx * dy : 0) + y; - - /* knee */ - Direction dir = Directional_element_interface::get (me); - Direction sdir = Directional_element_interface::get (s); - - /* knee */ - if (dir!= sdir) - { - stem_y -= dir - * (thick / 2 + (beam_multiplicity - 1) * interbeam_f); - - - - // huh, why not for first visible? - if (Staff_symbol_referencer::staff_symbol_l (s) - != Staff_symbol_referencer::staff_symbol_l (last_visible_stem (me))) - stem_y += Directional_element_interface::get (me) - * (beam_multiplicity - stem_multiplicity) * interbeam_f; - } - - return stem_y; -} - -Real -Beam::check_stem_length_f (Grob*me,Real y, Real dy) -{ - Real shorten = 0; - Real lengthen = 0; - Direction dir = Directional_element_interface::get (me); - - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); - - for (int i=0; i < stems.size (); i++) - { - Item* s = stems[i]; - if (Stem::invisible_b (s)) - continue; - - Real stem_y = calc_stem_y_f (me, s, y, dy); - - stem_y *= dir; - Stem_info info = Stem::calc_stem_info (s); - - // if (0 > info.maxy_f_ - stem_y) - shorten = shorten ? info.miny_f_ - stem_y; - } - - if (lengthen && shorten) - me->warning (_ ("weird beam vertical offset")); - - /* when all stems are too short, normal stems win */ - return dir * ((shorten) ? shorten : lengthen); -} - -/* - Hmm. At this time, beam position and slope are determined. Maybe, - stem directions and length should set to relative to the chord's - position of the beam. */ -void -Beam::set_stem_lengths (Grob *me) -{ - if (visible_stem_count (me) <= 1) - return; - - Real y = gh_scm2double (me->get_grob_property ("y")); - Real dy = gh_scm2double (me->get_grob_property ("dy")); - - Real half_space = Staff_symbol_referencer::staff_space (me)/2; - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); - - Grob *common = me->common_refpoint (stems[0], Y_AXIS); - for (int i=1; i < stems.size (); i++) - if (!Stem::invisible_b (stems[i])) - common = common->common_refpoint (stems[i], Y_AXIS); - - for (int i=0; i < stems.size (); i++) - { - Item* s = stems[i]; - if (Stem::invisible_b (s)) - continue; - - Real stem_y = calc_stem_y_f (me, s, y, dy); - - // doesn't play well with dvips - if (scm_definedp (ly_symbol2scm ("ps-testing"), SCM_UNDEFINED) - == SCM_BOOL_T) - if (Stem::get_direction (s) == Directional_element_interface::get (me)) - stem_y += Stem::get_direction (s) - * gh_scm2double (me->get_grob_property ("thickness")) / 2; - - /* caution: stem measures in staff-positions */ - Real id = me->relative_coordinate (common, Y_AXIS) - - stems[i]->relative_coordinate (common, Y_AXIS); - Stem::set_stemend (s, (stem_y + id) / half_space); - } -} - -/* - Prevent interference from stafflines and beams. - - We only need to quantise the (left) y of the beam, - since dy is quantised too. - if extend_b then stems must *not* get shorter - */ -Real -Beam::quantise_y_f (Grob*me,Real y, Real dy, int quant_dir) -{ - int multiplicity = get_multiplicity (me); - - Real staff_space = Staff_symbol_referencer::staff_space (me); - Real thick = me->paper_l ()->get_var ("stafflinethickness"); - - - SCM proc = me->get_grob_property ("vertical-position-quant-function"); - SCM quants = scm_apply (proc, - me->self_scm (), - scm_list_n (gh_int2scm (multiplicity), - gh_double2scm (dy/staff_space), - gh_double2scm (thick/staff_space), - SCM_EOL, SCM_UNDEFINED)); - - Array a; - - for (; gh_pair_p (quants); quants = ly_cdr (quants)) - a.push (gh_scm2double (ly_car (quants))); - - if (a.size () <= 1) - return y; - - Real up_y = Directional_element_interface::get (me) * y; - Interval iv = quantise_iv (a, up_y/staff_space) * staff_space; - - Real q = up_y - iv[SMALLER] <= iv[BIGGER] - up_y - ? iv[SMALLER] : iv[BIGGER]; - if (quant_dir) - q = iv[ (Direction)quant_dir]; - - return q * Directional_element_interface::get (me); -} - -void -Beam::set_beaming (Grob*me,Beaming_info_list *beaming) -{ - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems"); - - Direction d = LEFT; - for (int i=0; i < stems.size (); i++) - { - do - { - /* Don't overwrite user override (?) */ - if (Stem::beam_count (stems[i], d) == 0 - /* Don't set beaming for outside of outer stems */ - && ! (d == LEFT && i == 0) - && ! (d == RIGHT && i == stems.size () -1)) - { - int b = beaming->infos_.elem (i).beams_i_drul_[d]; - Stem::set_beaming (stems[i], b, d); - } - } - while (flip (&d) != LEFT); - } -} - - - -/* - beams to go with one stem. - - FIXME: clean me up. - */ -Molecule -Beam::stem_beams (Grob*me,Item *here, Item *next, Item *prev, - Real /* dy */ , Real dydx - ) -{ - // ugh -> use commonx - if ((next && ! (next->relative_coordinate (0, X_AXIS) > here->relative_coordinate (0, X_AXIS))) || - (prev && ! (prev->relative_coordinate (0, X_AXIS) < here->relative_coordinate (0, X_AXIS)))) - programming_error ("Beams are not left-to-right"); - - int multiplicity = get_multiplicity (me); - - SCM space_proc = me->get_grob_property ("space-function"); - SCM space = gh_call1 (space_proc, gh_int2scm (multiplicity)); - - Real thick = gh_scm2double (me->get_grob_property ("thickness")) ; - Real interbeam_f = gh_scm2double (space) ; - - Real bdy = interbeam_f; - -#if 0 - // ugh -> use commonx - Real dx = visible_stem_count (me) ? - last_visible_stem (me)->relative_coordinate (0, X_AXIS) - first_visible_stem (me)->relative_coordinate (0, X_AXIS) - : 0.0; -#endif - - Molecule leftbeams; - Molecule rightbeams; - - Real nw_f; - if (!Stem::first_head (here)) - nw_f = 0; - else { - int t = Stem::type_i (here); - - SCM proc = me->get_grob_property ("flag-width-function"); - SCM result = gh_call1 (proc, gh_int2scm (t)); - nw_f = gh_scm2double (result); - } - - - Direction dir = Directional_element_interface::get (me); - - /* [Tremolo] beams on whole notes may not have direction set? */ - if (dir == CENTER) - dir = Directional_element_interface::get (here); - - - /* half beams extending to the left. */ - if (prev) - { - int lhalfs= lhalfs = Stem::beam_count (here,LEFT) - Stem::beam_count (prev,RIGHT); - int lwholebeams= Stem::beam_count (here,LEFT) relative_coordinate (0, X_AXIS) - - prev->relative_coordinate (0, X_AXIS); - Real stem_w = gh_scm2double (prev->get_grob_property ("thickness")) - // URG - * me->paper_l ()->get_var ("stafflinethickness"); - - w = w/2 relative_coordinate (0, X_AXIS) - - here->relative_coordinate (0, X_AXIS); - - Real stem_w = gh_scm2double (next->get_grob_property ("thickness")) - // URG - * me->paper_l ()->get_var ("stafflinethickness"); - - Molecule a = Lookup::beam (dydx, w + stem_w, thick); - a.translate_axis (- stem_w/2, X_AXIS); - int j = 0; - Real gap_f = 0; - - SCM gap = me->get_grob_property ("gap"); - if (gh_number_p (gap)) - { - int gap_i = gh_scm2int ((gap)); - int nogap = rwholebeams - gap_i; - - for (; j < nogap; j++) - { - Molecule b (a); - b.translate_axis (-dir * bdy * j, Y_AXIS); - rightbeams.add_molecule (b); - } - if (Stem::invisible_b (here)) - gap_f = nw_f; - else - gap_f = nw_f / 2; - w -= 2 * gap_f; - a = Lookup::beam (dydx, w + stem_w, thick); - } - - for (; j < rwholebeams; j++) - { - Molecule b (a); - Real tx = 0; - if (Stem::invisible_b (here)) - // ugh, see chord-tremolo.ly - tx = (-dir + 1) / 2 * nw_f * 1.5 + gap_f/4; - else - tx = gap_f; - b.translate (Offset (tx, -dir * bdy * j)); - rightbeams.add_molecule (b); - } - - w = w/2 get_grob_property ("stems"))) - return SCM_EOL; - Real x0,dx; - Link_arraystems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); - if (visible_stem_count (me)) - { - // ugh -> use commonx - x0 = first_visible_stem (me)->relative_coordinate (0, X_AXIS); - dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - x0; - } - else - { - x0 = stems[0]->relative_coordinate (0, X_AXIS); - dx = stems.top ()->relative_coordinate (0, X_AXIS) - x0; - } - - - - /* - TODO: the naming of the grob properties sucks. - */ - SCM dy_s = me->get_grob_property ("dy"); - SCM y_s = me->get_grob_property ("y"); - - - Real dy = gh_number_p (dy_s) ? gh_scm2double (dy_s) : 0.0; - Real dydx = dy && dx ? dy/dx : 0; - Real y = gh_number_p (y_s) ? gh_scm2double (y_s) : 0.0; - - - for (int j=0; j 0)? stems[j-1] : 0; - Item * next = (j < stems.size ()-1) ? stems[j+1] :0; - - Molecule sb = stem_beams (me, i, next, prev, dy, dydx); - Real x = i->relative_coordinate (0, X_AXIS)-x0; - sb.translate (Offset (x, x * dydx + y)); - mol.add_molecule (sb); - } - mol.translate_axis (x0 - - dynamic_cast (me)->get_bound (LEFT)->relative_coordinate (0, X_AXIS), X_AXIS); - - return mol.smobbed_copy (); -} - -int -Beam::forced_stem_count (Grob*me) -{ - Link_arraystems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); - int f = 0; - for (int i=0; i < stems.size (); i++) - { - Item *s = stems[i]; - - if (Stem::invisible_b (s)) - continue; - - if (( (int)Stem::chord_start_f (s)) - && (Stem::get_direction (s) != Stem::get_default_dir (s))) - f++; - } - return f; -} - - - - -/* TODO: - use filter and standard list functions. - */ -int -Beam::visible_stem_count (Grob*me) -{ - Link_arraystems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); - int c = 0; - for (int i = stems.size (); i--;) - { - if (!Stem::invisible_b (stems[i])) - c++; - } - return c; -} - -Item* -Beam::first_visible_stem (Grob*me) -{ - Link_arraystems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); - - for (int i = 0; i < stems.size (); i++) - { - if (!Stem::invisible_b (stems[i])) - return stems[i]; - } - return 0; -} - -Item* -Beam::last_visible_stem (Grob*me) -{ - Link_arraystems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); - for (int i = stems.size (); i--;) - { - if (!Stem::invisible_b (stems[i])) - return stems[i]; - } - return 0; -} - - -/* - [TODO] - handle rest under beam (do_post: beams are calculated now) - what about combination of collisions and rest under beam. - - Should lookup - - rest -> stem -> beam -> interpolate_y_position () -*/ -MAKE_SCHEME_CALLBACK (Beam,rest_collision_callback,2); -SCM -Beam::rest_collision_callback (SCM element_smob, SCM axis) -{ - Grob *rest = unsmob_grob (element_smob); - Axis a = (Axis) gh_scm2int (axis); - - assert (a == Y_AXIS); - - Grob * st = unsmob_grob (rest->get_grob_property ("stem")); - Grob * stem = st; - if (!stem) - return gh_double2scm (0.0); - Grob * beam = unsmob_grob (stem->get_grob_property ("beam")); - if (!beam || !Beam::has_interface (beam) || !Beam::visible_stem_count (beam)) - return gh_double2scm (0.0); - - // make callback for rest from this. - Real beam_dy = 0; - Real beam_y = 0; - - - // todo: make sure this calced already. - SCM s = beam->get_grob_property ("dy"); - if (gh_number_p (s)) - beam_dy = gh_scm2double (s); - - s = beam->get_grob_property ("y"); - if (gh_number_p (s)) - beam_y = gh_scm2double (s); - - // ugh -> use commonx - Real x0 = first_visible_stem (beam)->relative_coordinate (0, X_AXIS); - Real dx = last_visible_stem (beam)->relative_coordinate (0, X_AXIS) - x0; - Real dydx = beam_dy && dx ? beam_dy/dx : 0; - - Direction d = Stem::get_direction (stem); - Real beamy = (stem->relative_coordinate (0, X_AXIS) - x0) * dydx + beam_y; - - Real staff_space = Staff_symbol_referencer::staff_space (rest); - - - Real rest_dim = rest->extent (rest, Y_AXIS)[d]*2.0 / staff_space ; // refp?? - - Real minimum_dist - = gh_scm2double (rest->get_grob_property ("minimum-beam-collision-distance")); - Real dist = - minimum_dist + -d * (beamy - rest_dim) >? 0; - - int stafflines = Staff_symbol_referencer::line_count (rest); - - // move discretely by half spaces. - int discrete_dist = int (ceil (dist)); - - // move by whole spaces inside the staff. - if (discrete_dist < stafflines+1) - discrete_dist = int (ceil (discrete_dist / 2.0)* 2.0); - - return gh_double2scm (-d * discrete_dist); -} - - -bool -Beam::has_interface (Grob*me) -{ - return me->has_interface (ly_symbol2scm ("beam-interface")); -} - diff --git a/lily/include/note-spacing.hh b/lily/include/note-spacing.hh index cedd931120..84424f188b 100644 --- a/lily/include/note-spacing.hh +++ b/lily/include/note-spacing.hh @@ -17,8 +17,8 @@ class Note_spacing public: static bool has_interface (Grob*); - static Real get_spacing (Grob *me); - static Real stem_dir_correction (Grob *me); + static void get_spacing (Grob *me, Item* , Real, Real, Real*, Real*); + static Real stem_dir_correction (Grob *me, Item * next_col); static Item * right_column (Grob*); static Item * left_column (Grob*); }; diff --git a/lily/note-spacing.cc b/lily/note-spacing.cc index 88beea3142..8f29e28dd1 100644 --- a/lily/note-spacing.cc +++ b/lily/note-spacing.cc @@ -24,20 +24,34 @@ Note_spacing::has_interface (Grob* g) return g && g->has_interface (ly_symbol2scm ("note-spacing-interface")); } -Real -Note_spacing::get_spacing (Grob *me) +void +Note_spacing::get_spacing (Grob *me, Item* right_col, + Real base_space, Real increment, Real *space, Real *fixed) { + Drul_array props(me->get_grob_property ("left-items"), me->get_grob_property ("right-items")); Direction d = LEFT; + Direction col_dir = right_col->break_status_dir (); Drul_array extents; do { for (SCM s = props[d]; gh_pair_p (s); s = gh_cdr (s)) { Item * it= dynamic_cast (unsmob_grob (gh_car(s))); - extents[d].unite (it->extent (it->column_l (), X_AXIS)); + if (d == RIGHT && it->break_status_dir () != col_dir) + { + it = it -> find_prebroken_piece (col_dir); + } + /* + some kind of mismatch, eg. a note column, that is behind a + linebreak. + */ + if (!it) + continue; + + extents[d].unite (it->extent (it->column_l (), X_AXIS)); if (d == RIGHT) { Grob * accs = Note_column::accidentals (it); @@ -54,14 +68,23 @@ Note_spacing::get_spacing (Grob *me) } while (flip (&d) != LEFT); - /* + *fixed = (extents[LEFT][RIGHT] >? increment); + *space = (base_space - increment) + *fixed ; + + if (*space - *fixed < 2 * ((- extents[RIGHT][LEFT]) >? 0)) + { + /* - What's sticking out at the left of the right side has less - influence. + What's sticking out at the left of the right side has less + influence. We only take it into account if there is not enough + space. - */ - Real dx= extents[LEFT][RIGHT] - 0.5 * extents[RIGHT][LEFT]; - return dx; + this sucks: this criterion is discontinuous; FIXME. + */ + *space += 0.5 * (( -extents[RIGHT][LEFT]) >? 0); + } + + *space += stem_dir_correction (me, right_col); } Item * @@ -149,7 +172,7 @@ Note_spacing::right_column (Grob*me) */ Real -Note_spacing::stem_dir_correction (Grob*me) +Note_spacing::stem_dir_correction (Grob*me, Item * rcolumn) { Drul_array stem_dirs(CENTER,CENTER); Drul_array stem_posns; @@ -183,6 +206,11 @@ Note_spacing::stem_dir_correction (Grob*me) { if (d == RIGHT && Separation_item::has_interface (it)) { + if (it->column_l () != rcolumn) + { + it = it->find_prebroken_piece (rcolumn->break_status_dir ()); + } + Grob *last = Staff_spacing::extremal_break_aligned_grob (it, LEFT, &bar_xextent); if (last) @@ -193,6 +221,7 @@ Note_spacing::stem_dir_correction (Grob*me) goto exit_func; } + if(Stem::invisible_b (stem)) { correct = false; diff --git a/lily/simple-spacer.cc b/lily/simple-spacer.cc index 694625bf75..f6a36eaa48 100644 --- a/lily/simple-spacer.cc +++ b/lily/simple-spacer.cc @@ -77,9 +77,25 @@ Simple_spacer::add_rod (int l, int r, Real dist) programming_error ("Weird minimum distance. Ignoring"); return; } - - + Real c = range_stiffness (l,r); + if (isinf (c)) + { + /* + If a spring is fixed, we have to do something here: + we let the rod override the spring. + */ + Real total_dist = 0.; + for (int i = l ; i < r; i++) + total_dist += springs_[i].ideal_f_; + + if (total_dist < dist) + for (int i = l ; i < r; i++) + springs_[i].ideal_f_ *= dist/total_dist; + + return; + } + Real d = range_ideal_len (l,r); Real block_stretch = dist - d; diff --git a/lily/spaceable-grob.cc b/lily/spaceable-grob.cc index 325efaaae8..2695186b5d 100644 --- a/lily/spaceable-grob.cc +++ b/lily/spaceable-grob.cc @@ -44,6 +44,11 @@ Spaceable_grob::add_rod (Grob *me , Grob * p, Real d) void Spaceable_grob::add_spring (Grob*me, Grob * p, Real d, Real strength, bool expand_only) { + if (d < 0.0 || strength <= 0.0) + { + programming_error ("Adding reverse spring!"); + } + #ifndef NDEBUG SCM mins = me->get_grob_property ("ideal-distances"); for (SCM s = mins; gh_pair_p (s); s = ly_cdr (s)) diff --git a/lily/spacing-spanner.cc b/lily/spacing-spanner.cc index ffce2a7ac7..de49d2c35b 100644 --- a/lily/spacing-spanner.cc +++ b/lily/spacing-spanner.cc @@ -31,7 +31,6 @@ a little baroque, but it might come in handy later on? */ - class Spacing_spanner { public: @@ -41,11 +40,12 @@ public: static Rational find_shortest (Link_array const &); static void breakable_column_spacing (Item* l, Item *r); static void find_loose_columns () {} - static void prune_loose_colunms (Link_array *cols); + static void prune_loose_colunms (Grob*,Link_array *cols, Rational); static void find_loose_columns (Link_array cols); static void set_explicit_neighbor_columns (Link_array cols); static void set_implicit_neighbor_columns (Link_array cols); static void do_measure (Rational, Grob*me,Link_array *cols); + static void musical_column_spacing (Grob*,Item*,Item*, Real, Rational); DECLARE_SCHEME_CALLBACK (set_springs, (SCM )); }; @@ -77,9 +77,7 @@ loose_column (Grob *l, Grob *c, Grob *r) the column containing the clef is really loose, and should be attached right to the first column, but that is a lot of work for - such a borderline case. - - ) + such a borderline case.) */ if (!gh_pair_p (lns) || !gh_pair_p (rns)) @@ -105,7 +103,7 @@ loose_column (Grob *l, Grob *c, Grob *r) some cases (two isolated, consecutive clef changes) won't be nicely folded, but hey, then don't do that. */ - if( (Paper_column::musical_b (l_neighbor) || Item::breakable_b (l_neighbor)) + if ((Paper_column::musical_b (l_neighbor) || Item::breakable_b (l_neighbor)) && (Paper_column::musical_b (r_neighbor) || Item::breakable_b (r_neighbor))) { return true; @@ -128,10 +126,10 @@ loose_column (Grob *l, Grob *c, Grob *r) between. */ void -Spacing_spanner::prune_loose_colunms (Link_array *cols) +Spacing_spanner::prune_loose_colunms (Grob*me,Link_array *cols, Rational shortest) { Link_array newcols; - + Real increment = gh_scm2double (me->get_grob_property ("spacing-increment")); for (int i=0; i < cols->size (); i++) { if (Item::breakable_b (cols->elem(i)) || Paper_column::musical_b (cols->elem (i))) @@ -169,8 +167,8 @@ Spacing_spanner::prune_loose_colunms (Link_array *cols) do { dists[d] = 0.0; - Grob *lc = (d == LEFT) ? next_door[LEFT] : c; - Grob *rc = d == LEFT ? c : next_door[RIGHT]; + Item *lc = dynamic_cast ((d == LEFT) ? next_door[LEFT] : c); + Item *rc = dynamic_cast (d == LEFT ? c : next_door[RIGHT]); for (SCM s = lc->get_grob_property ("spacing-wishes"); gh_pair_p (s); s = gh_cdr (s)) @@ -180,7 +178,14 @@ Spacing_spanner::prune_loose_colunms (Link_array *cols) || Note_spacing::right_column (sp) != rc) continue; - dists[d] = dists[d] >? Note_spacing::get_spacing (sp); + Real space, fixed; + fixed = 0.0; + bool expand_only; + Real base = note_spacing (me, lc, rc, shortest, &expand_only); + Note_spacing::get_spacing (sp, rc, base, increment, &space, &fixed); + space -=base; + + dists[d] = dists[d] >? space; } } while (flip (&d) != LEFT); @@ -312,10 +317,11 @@ Spacing_spanner::set_springs (SCM smob) Link_array all (me->pscore_l_->line_l_->column_l_arr ()) ; set_explicit_neighbor_columns (all); - prune_loose_colunms (&all); - set_implicit_neighbor_columns (all); Rational global_shortest = find_shortest (all); + prune_loose_colunms (me, &all, global_shortest); + set_implicit_neighbor_columns (all); + int j = 0; for (int i = 1; i < all.size (); i++) @@ -461,73 +467,64 @@ Spacing_spanner::do_measure (Rational shortest, Grob*me, Link_array *cols) continue ; } - bool expand_only = false; - Real note_space = note_spacing (me, lc, rc, shortest, &expand_only); - - Real hinterfleisch = note_space; - - - SCM seq = lc->get_grob_property ("right-neighbors"); - /* - hinterfleisch = hind-meat = amount of space following a note. - - - We adjust the space following a note only if the next note - happens after the current note (this is set in the grob - property SPACING-SEQUENCE. */ - Real stretch_distance = note_space; + musical_column_spacing (me, lc, rc, headwid, shortest); + if (Item *rb = r->find_prebroken_piece (LEFT)) + musical_column_spacing (me, lc, rb, headwid, shortest); + } +} - hinterfleisch = -1.0; - Real max_factor = 0.0; - for (SCM s = seq; gh_pair_p (s); s = ly_cdr (s)) - { - Grob * wish = unsmob_grob (gh_car (s)); +void +Spacing_spanner::musical_column_spacing (Grob *me, Item * lc, Item *rc, Real increment, Rational shortest) +{ + bool expand_only = false; + Real base_note_space = note_spacing (me, lc, rc, shortest, &expand_only); - if (Note_spacing::left_column (wish) != lc - || Note_spacing::right_column (wish) != rc) - continue; + Real max_note_space = -infinity_f; + Real max_fixed_note_space = -infinity_f; - /* - This is probably a waste of time in the case of polyphonic - music. */ - if (Note_spacing::has_interface (wish)) - { - hinterfleisch = hinterfleisch >? - ( - headwid + + SCM seq = lc->get_grob_property ("right-neighbors"); - (note_space + Note_spacing::get_spacing (wish)) - *gh_scm2double (wish->get_grob_property ("space-factor")) + /* + We adjust the space following a note only if the next note + happens after the current note (this is set in the grob + property SPACING-SEQUENCE. + */ + for (SCM s = seq; gh_pair_p (s); s = ly_cdr (s)) + { + Grob * wish = unsmob_grob (gh_car (s)); - + Note_spacing::stem_dir_correction (wish)); - } - } + Item *wish_rcol = Note_spacing::right_column (wish); + if (Note_spacing::left_column (wish) != lc + || (wish_rcol != rc && wish_rcol != rc->original_l_)) + continue; - if (hinterfleisch < 0) + /* + This is probably a waste of time in the case of polyphonic + music. */ + if (Note_spacing::has_interface (wish)) { - // maybe should issue a programming error. - hinterfleisch = note_space; + Real space =0.0; + Real fixed =0.0; + + Note_spacing::get_spacing (wish, rc, base_note_space, increment, &space, &fixed); + max_note_space = max_note_space >? space; + max_fixed_note_space = max_fixed_note_space >? fixed; } - else - stretch_distance -= headwid; // why? - if (max_factor == 0.0) - max_factor = 1.0; - - Spaceable_grob::add_spring (l, r, max_factor * hinterfleisch, 1 / stretch_distance, expand_only); + } - /* - TODO: we should have a separate routine determining this distance! - */ - if (Item *rb = r->find_prebroken_piece (LEFT)) - { - Spaceable_grob::add_spring (l, rb, max_factor * hinterfleisch, 1 / stretch_distance, expand_only); - } + if (max_note_space < 0) + { + max_note_space = base_note_space; + max_fixed_note_space = increment; } + Spaceable_grob::add_spring (lc, rc, max_note_space, 1 / (max_note_space -max_fixed_note_space), expand_only); } + /* Read hints from L (todo: R) and generate springs. */ @@ -540,7 +537,7 @@ Spacing_spanner::breakable_column_spacing (Item* l, Item *r) for (SCM s = l->get_grob_property ("spacing-wishes"); gh_pair_p (s); s = gh_cdr (s)) { - Grob * spacing_grob = unsmob_grob (gh_car (s)); + Item * spacing_grob = dynamic_cast (unsmob_grob (gh_car (s))); if (!spacing_grob || !Staff_spacing::has_interface (spacing_grob)) continue; @@ -548,6 +545,13 @@ Spacing_spanner::breakable_column_spacing (Item* l, Item *r) Real space; Real fixed_space; + /* + column for the left one settings should be ok due automatic + pointer munging. + + */ + assert (spacing_grob-> column_l () == l); + Staff_spacing::get_spacing_params (spacing_grob, &space, &fixed_space); if (space > max_space) @@ -564,6 +568,19 @@ Spacing_spanner::breakable_column_spacing (Item* l, Item *r) max_fixed = 1.0; } + + if (l->break_status_dir() == RIGHT + && Paper_column::when_mom (l) == Paper_column::when_mom (r)) + { + /* Start of line: this space is not stretchable */ + max_fixed = max_space; + } + + /* + Hmm. we do 1/0 in the next thing. Perhaps we should check if this + works on all architectures. + */ + Spaceable_grob::add_spring (l, r, max_space, 1/(max_space - max_fixed), false); } diff --git a/lily/staff-spacing.cc b/lily/staff-spacing.cc index 8493dd9326..5eab8ffbf2 100644 --- a/lily/staff-spacing.cc +++ b/lily/staff-spacing.cc @@ -40,11 +40,19 @@ Staff_spacing::next_note_correction (Grob * me, Item *col =dynamic_cast (g)->column_l (); Real max_corr = 0. >? (- g->extent (col, X_AXIS)[LEFT]); + + /* + Duh. If this gets out of hand, we should invent something more generic. + */ if (Grob * a = Note_column::accidentals (g)) { max_corr = max_corr >? (- a->extent (col, X_AXIS)[LEFT]); } - + if (Grob* a = unsmob_grob (g->get_grob_property ("arpeggio"))) + { + max_corr = max_corr >? (- a->extent (col, X_AXIS)[LEFT]); + } + /* Let's decrease the space a little if the problem is not located after a barline. @@ -223,11 +231,4 @@ Staff_spacing::get_spacing_params (Grob *me, Real * space, Real * fixed) *space += next_notes_correction (me, last_grob); - - if (dynamic_cast (me)-> break_status_dir () == RIGHT) - { - /* Start of line: this space is not stretchable */ - *fixed = *space; - } - } diff --git a/make/out/lilypond.lsm b/make/out/lilypond.lsm index be36f34f9a..3dc3e419dd 100644 --- a/make/out/lilypond.lsm +++ b/make/out/lilypond.lsm @@ -1,15 +1,15 @@ Begin3 Title: LilyPond -Version: 1.5.38 -Entered-date: 11MRT02 +Version: 1.5.39 +Entered-date: 13MRT02 Description: @BLURB@ Keywords: music notation typesetting midi fonts engraving Author: hanwen@cs.uu.nl (Han-Wen Nienhuys) janneke@gnu.org (Jan Nieuwenhuizen) Maintained-by: hanwen@stack.nl (Han-Wen Nienhuys) Primary-site: sunsite.unc.edu /pub/Linux/apps/sound/convert - 1000k lilypond-1.5.38.tar.gz + 1000k lilypond-1.5.39.tar.gz Original-site: ftp.cs.uu.nl /pub/GNU/LilyPond/development/ - 1000k lilypond-1.5.38.tar.gz + 1000k lilypond-1.5.39.tar.gz Copying-policy: GPL End diff --git a/make/out/lilypond.mandrake.spec b/make/out/lilypond.mandrake.spec index 0a2dc2df67..d7ec834ed6 100644 --- a/make/out/lilypond.mandrake.spec +++ b/make/out/lilypond.mandrake.spec @@ -1,5 +1,5 @@ %define name lilypond -%define version 1.5.38 +%define version 1.5.39 %define release 1mdk Name: %{name} diff --git a/make/out/lilypond.redhat.spec b/make/out/lilypond.redhat.spec index dae2b110c1..5ebee819d0 100644 --- a/make/out/lilypond.redhat.spec +++ b/make/out/lilypond.redhat.spec @@ -3,11 +3,11 @@ %define info yes Name: lilypond -Version: 1.5.38 +Version: 1.5.39 Release: 1 License: GPL Group: Applications/Publishing -Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.5.38.tar.gz +Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.5.39.tar.gz Summary: Create and print music notation URL: http://www.lilypond.org/ BuildRoot: /tmp/lilypond-install diff --git a/make/out/lilypond.suse.spec b/make/out/lilypond.suse.spec index ae5354adc1..012c51fa44 100644 --- a/make/out/lilypond.suse.spec +++ b/make/out/lilypond.suse.spec @@ -14,11 +14,11 @@ Distribution: SuSE Linux 7.0 (i386) Name: lilypond -Version: 1.5.38 +Version: 1.5.39 Release: 2 Copyright: GPL Group: Applications/Publishing -Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.5.38.tar.gz +Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.5.39.tar.gz # music notation software for.. ? Summary: A program for printing sheet music. URL: http://www.lilypond.org/ diff --git a/mf/feta-klef.mf b/mf/feta-klef.mf index 5f17ff4b28..6086c6eeea 100644 --- a/mf/feta-klef.mf +++ b/mf/feta-klef.mf @@ -227,7 +227,7 @@ def draw_bass_clef(expr exact_center, reduction) = pickup pencircle scaled 1; % draw fill - new_bulb (z1, 0.4 reduced_ss, 0.35 reduced_ss, 2 stafflinethickness, 1) + new_bulb (z1, 0.45 reduced_ss, 0.4 reduced_ss, 2.5 stafflinethickness, 1) {dir (90)} .. z2r{right} .. tension 1.0 .. z3r{down} .. {curl 0} diff --git a/scm/grob-description.scm b/scm/grob-description.scm index d441d1aa37..96f1112f4f 100644 --- a/scm/grob-description.scm +++ b/scm/grob-description.scm @@ -20,7 +20,7 @@ (after-line-breaking-callback . ,Local_key_item::after_line_breaking) (direction . -1) (left-padding . 0.2) - (right-padding . 0.4) + (right-padding . 0.5) (paren-cautionaries . #t) (font-family . music) (meta . ,(grob-description accidentals-interface font-interface side-position-interface)) @@ -52,7 +52,7 @@ (time-signature . (extra-space . 0.75)) (custos . (minimum-space . 2.0)) (clef . (minimum-space . 1.0)) - (begin-of-note . (extra-space . 1.0)) + (begin-of-note . (extra-space . 1.3)) )) ;; @@ -636,6 +636,7 @@ (shortest-duration-space . 2.0) (spacing-increment . 1.2) + (X-extent-callback . #f) (Y-extent-callback . #f) diff --git a/scm/grob-property-description.scm b/scm/grob-property-description.scm index 2e63f3e81e..92a6026363 100644 --- a/scm/grob-property-description.scm +++ b/scm/grob-property-description.scm @@ -47,6 +47,7 @@ with this much space for the shortest duration. This is explessed in @code{spaci @ref{spacing-spanner-interface}.") (grob-property-description 'spacing-increment number? "Add this much space for a doubled duration. Typically, the width of a note head. See also @ref{spacing-spanner-interface}.") +(grob-property-description 'arpeggio ly-grob? "pointer to arpeggio object.") (grob-property-description 'arpeggio-direction dir? "If set, put an arrow on the arpeggio squiggly line.") (grob-property-description 'attachment pair? "cons of symbols, '(LEFT-TYPE . RIGHT-TYPE), where both types may be alongside-stem, stem, head or loose-end.")