+++ /dev/null
-/*
- bar.cc -- implement Bar
-
- source file of the GNU LilyPond music typesetter
-
- (c) 1997--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
-*/
-#include <math.h>
-
-#include "lookup.hh"
-#include "paper-column.hh"
-#include "main.hh"
-#include "grob.hh"
-#include "bar.hh"
-#include "string.hh"
-#include "molecule.hh"
-#include "paper-def.hh"
-#include "font-interface.hh"
-#include "debug.hh"
-#include "all-font-metrics.hh"
-#include "item.hh"
-#include "staff-symbol-referencer.hh"
-
-MAKE_SCHEME_CALLBACK (Bar,brew_molecule,1);
-
-SCM
-Bar::brew_molecule (SCM smob)
-{
- Grob * me = unsmob_grob (smob);
-
- SCM s = me->get_grob_property ("glyph");
- SCM barsiz_proc = me->get_grob_property ("bar-size-procedure");
- if (gh_string_p (s) && gh_procedure_p (barsiz_proc))
- {
- String str =ly_scm2string (s);
- SCM siz = gh_call1 (barsiz_proc, me->self_scm ());
- Real sz = gh_scm2double (siz);
- if (sz < 0)
- return SCM_EOL;
-
- return compound_barline (me, str, sz).smobbed_copy ();
- }
- return SCM_EOL;
-}
-
-
-Molecule
-Bar::compound_barline (Grob*me, String str, Real h)
-{
- Real kern = gh_scm2double (me->get_grob_property ("kern"));
- Real thinkern = gh_scm2double (me->get_grob_property ("thin-kern"));
- Real hair = gh_scm2double (me->get_grob_property ("hair-thickness"));
- Real fatline = gh_scm2double (me->get_grob_property ("thick-thickness"));
-
- Real staffline = me->paper_l ()->get_var ("stafflinethickness");
- Real staff_space = Staff_symbol_referencer::staff_space (me);
- Real staffspace = me->paper_l ()->get_var ("staffspace")
- * staff_space;
-
- kern *= staffline;
- thinkern *= staffline;
- hair *= staffline;
- fatline *= staffline;
-
- Molecule thin = simple_barline (me, hair, h);
- Molecule thick = simple_barline (me, fatline, h);
- Molecule colon;
- Molecule dot = Font_interface::get_default_font (me)->find_by_name ("dots-dot");
- Real dist = ( Staff_symbol_referencer::line_count (me) & 1 ? 1 :
- staff_space<2 ? 2 : .5 ) * staffspace;
- dot.translate_axis(dist/2,Y_AXIS);
- colon.add_molecule(dot);
- dot.translate_axis(-dist,Y_AXIS);
- colon.add_molecule(dot);
-
- Molecule m;
-
- if (str == "")
- {
- return Lookup::blank (Box (Interval (0, 0), Interval (-h/2, h/2)));
- }
- else if (str == "|")
- {
- return thin;
- }
- else if (str == "|." || (h == 0 && str == ":|"))
- {
- m.add_at_edge (X_AXIS, LEFT, thick, 0);
- m.add_at_edge (X_AXIS, LEFT, thin, kern);
- }
- else if (str == ".|" || (h == 0 && str == "|:"))
- {
- m.add_at_edge (X_AXIS, RIGHT, thick, 0);
- m.add_at_edge (X_AXIS, RIGHT, thin, kern);
- }
- else if (str == ":|")
- {
- m.add_at_edge (X_AXIS, LEFT, thick, 0);
- m.add_at_edge (X_AXIS, LEFT, thin, kern);
- m.add_at_edge (X_AXIS, LEFT, colon, kern);
- }
- else if (str == "|:")
- {
- m.add_at_edge (X_AXIS, RIGHT, thick, 0);
- m.add_at_edge (X_AXIS, RIGHT, thin, kern);
- m.add_at_edge (X_AXIS, RIGHT, colon, kern);
- }
- else if (str == ":|:")
- {
- m.add_at_edge (X_AXIS, LEFT, thick, thinkern);
- m.add_at_edge (X_AXIS, LEFT, colon, kern);
- m.add_at_edge (X_AXIS, RIGHT, thick, kern);
- m.add_at_edge (X_AXIS, RIGHT, colon, kern);
- }
- else if (str == ".|.")
- {
- m.add_at_edge (X_AXIS, LEFT, thick, thinkern);
- m.add_at_edge (X_AXIS, RIGHT, thick, kern);
- }
- else if (str == "||")
- {
- m.add_at_edge (X_AXIS, RIGHT, thin, 0);
- m.add_at_edge (X_AXIS, RIGHT, thin, thinkern);
- }
-
- return m;
-}
-
-
-Molecule
-Bar::simple_barline (Grob*,Real w, Real h)
-{
- return Lookup::filledbox (Box (Interval (0,w), Interval (-h/2, h/2)));
-}
-
-MAKE_SCHEME_CALLBACK (Bar,before_line_breaking ,1);
-
-SCM
-Bar::before_line_breaking (SCM smob)
-{
- Grob*me=unsmob_grob (smob);
- Item * item = dynamic_cast<Item*> (me);
-
- SCM g = me->get_grob_property ("glyph");
- SCM orig = g;
- Direction bsd = item->break_status_dir ();
- if (gh_string_p (g) && bsd)
- {
- SCM proc = me->get_grob_property ("break-glyph-function");
- g = gh_call2 (proc, g, gh_int2scm (bsd));
- }
-
-
- if (!gh_string_p (g))
- {
- me->set_grob_property ("molecule-callback", SCM_EOL);
- me->set_extent_callback (SCM_EOL, X_AXIS);
- // leave y_extent for spanbar?
- }
-
- if (! gh_equal_p (g, orig))
- me->set_grob_property ("glyph", g);
-
- return SCM_UNSPECIFIED;
-}
-
-void
-Bar::set_interface (Grob*me)
-{
- me->set_interface (ly_symbol2scm ("bar-line-interface"));
-}
-
-bool
-Bar::has_interface (Grob*m)
-{
- return m && m->has_interface (ly_symbol2scm ("bar-line-interface"));
-}
-
-
-MAKE_SCHEME_CALLBACK (Bar,get_staff_bar_size,1);
-SCM
-Bar::get_staff_bar_size (SCM smob)
-{
- Grob*me = unsmob_grob (smob);
- Real ss = Staff_symbol_referencer::staff_space (me);
- SCM size = me->get_grob_property ("bar-size");
- if (gh_number_p (size))
- return gh_double2scm (gh_scm2double (size)*ss);
- else if (Staff_symbol_referencer::staff_symbol_l (me))
- {
- /*
- If there is no staff-symbol, we get -1 from the next
- calculation. That's a nonsense value, which would collapse the
- barline so we return 0.0 in the next alternative.
- */
- return gh_double2scm ((Staff_symbol_referencer::line_count (me) -1) * ss);
- }
- else
- return gh_int2scm (0);
-}
+++ /dev/null
-/*
- break-align-item.cc -- implement Break_align_interface
-
- source file of the GNU LilyPond music typesetter
-
- (c) 1997--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
-*/
-
-
-#include <math.h>
-#include <libc-extension.hh> // isinf
-
-#include "side-position-interface.hh"
-#include "axis-group-interface.hh"
-#include "warn.hh"
-#include "lily-guile.hh"
-#include "break-align-item.hh"
-#include "dimensions.hh"
-#include "paper-def.hh"
-#include "paper-column.hh"
-#include "group-interface.hh"
-#include "align-interface.hh"
-
-MAKE_SCHEME_CALLBACK (Break_align_interface,before_line_breaking,1);
-
-SCM
-Break_align_interface::before_line_breaking (SCM smob)
-{
- Grob* me = unsmob_grob (smob);
- do_alignment (me);
- return SCM_UNSPECIFIED;
-}
-MAKE_SCHEME_CALLBACK (Break_align_interface,alignment_callback,2);
-
-SCM
-Break_align_interface::alignment_callback (SCM element_smob, SCM axis)
-{
- Grob *me = unsmob_grob (element_smob);
- Axis a = (Axis) gh_scm2int (axis);
-
- assert (a == X_AXIS);
- Grob *par = me->get_parent (a);
- if (par && !to_boolean (par->get_grob_property ("break-alignment-done")))\
- {
- par->set_grob_property ("break-alignment-done", SCM_BOOL_T);
- Break_align_interface::do_alignment (par);
- }
-
- return gh_double2scm (0);
-}
-
-MAKE_SCHEME_CALLBACK (Break_align_interface,self_align_callback,2);
-SCM
-Break_align_interface::self_align_callback (SCM element_smob, SCM axis)
-{
- Grob *me = unsmob_grob (element_smob);
- Axis a = (Axis) gh_scm2int (axis);
- assert (a == X_AXIS);
-
- Item* item = dynamic_cast<Item*> (me);
- Direction bsd = item->break_status_dir ();
- if (bsd == LEFT)
- {
- me->set_grob_property ("self-alignment-X", gh_int2scm (RIGHT));
- }
-
- /*
- Force break alignment itself to be done first, in the case
- */
-
-
- return Side_position_interface::aligned_on_self (element_smob, axis);
-}
-
-void
-Break_align_interface::add_element (Grob*me, Grob *toadd)
-{
- Axis_group_interface::add_element (me, toadd);
-}
-
-void
-Break_align_interface::do_alignment (Grob *me)
-{
- Item * item = dynamic_cast<Item*> (me);
- Item *column = item->column_l ();
-
- Link_array<Grob> elems;
- Link_array<Grob> all_elems
- = Pointer_group_interface__extract_grobs (me, (Grob*)0,
- "elements");
-
- for (int i=0; i < all_elems.size (); i++)
- {
- Interval y = all_elems[i]->extent (all_elems[i], X_AXIS);
- if (!y.empty_b ())
- elems.push (dynamic_cast<Grob*> (all_elems[i]));
- }
-
- if (!elems.size ())
- return;
-
- SCM symbol_list = SCM_EOL;
- Array<Real> dists;
- SCM current_origin = ly_symbol2scm ("none");
- for (int i=0; i <= elems.size (); i++)
- {
- Grob *next_elt = i < elems.size ()
- ? elems[i]
- : 0 ;
-
- SCM next_origin;
-
- if (next_elt)
- {
- next_origin = next_elt->get_grob_property ("break-align-symbol");
- next_origin =
- gh_symbol_p (next_origin)?
- next_origin : ly_symbol2scm ("none")
-;
- }
- else
- next_origin = ly_symbol2scm ("begin-of-note");
-
- SCM alist = me->get_grob_property ("space-alist");
- SCM e = scm_assoc (scm_list_n (current_origin,
- next_origin,
- SCM_UNDEFINED), alist);
-
- SCM extra_space;
- if (e != SCM_BOOL_F)
- {
- extra_space = ly_cdr (e);
- }
- else
- {
- warning (_f ("unknown spacing pair `%s', `%s'",
- ly_symbol2string (current_origin),
- ly_symbol2string (next_origin)));
- extra_space = scm_list_n (ly_symbol2scm ("minimum-space-pair"), gh_double2scm (0.0), SCM_UNDEFINED);
- }
-
- SCM symbol = ly_car (extra_space);
- Real spc = gh_scm2double (ly_cadr (extra_space));
-
- dists.push (spc);
- symbol_list = gh_cons (symbol, symbol_list);
- current_origin = next_origin;
- }
-
-
- // skip the first sym.
- symbol_list = ly_cdr (scm_reverse (symbol_list));
- for (int i=0; i <elems.size ()-1; i++)
- {
- elems[i]->internal_set_grob_property (ly_car (symbol_list),
- scm_cons (gh_double2scm (0),
- gh_double2scm (dists[i+1])));
-
- symbol_list = ly_cdr (symbol_list);
- }
-
-
- // urg
- SCM first_pair = elems[0]->get_grob_property ("minimum-space-pair");
- if (gh_pair_p (first_pair))
- first_pair = first_pair;
- else
- first_pair = gh_cons (gh_double2scm (0.0), gh_double2scm (0.0));
-
- scm_set_car_x (first_pair, gh_double2scm (-dists[0]));
- elems[0]->set_grob_property ("minimum-space-pair", first_pair);
-
- Direction bsd = item->break_status_dir ();
- if (bsd == LEFT)
- {
- me->set_grob_property ("self-alignment-X", gh_int2scm (RIGHT));
- }
-
- /*
- Force callbacks for alignment to be called
- */
- Align_interface::align_elements_to_extents (me, X_AXIS);
-
- Real pre_space = elems[0]->relative_coordinate (column, X_AXIS);
-
- Real xl = elems[0]->extent (elems[0],X_AXIS)[LEFT];
- if (!isinf (xl))
- pre_space += xl;
- else
- programming_error ("Infinity reached. ");
-
- Real xr = elems.top ()->extent (elems.top (), X_AXIS)[RIGHT];
- Real spring_len = elems.top ()->relative_coordinate (column, X_AXIS);
- if (!isinf (xr))
- spring_len += xr;
- else
- programming_error ("Infinity reached.");
-
- Real stretch_distance =0.;
-
- if (ly_car (symbol_list) == ly_symbol2scm ("extra-space"))
- {
- spring_len += dists.top ();
- stretch_distance = dists.top ();
- }
- else if (ly_car (symbol_list) == ly_symbol2scm ("minimum-space-pair"))
- {
- spring_len = spring_len >? dists.top ();
- stretch_distance = spring_len;
- }
-
-
- /*
- Hint the spacing engine how much space to put in.
-
- The pairs are in the format of an interval (ie. CAR < CDR).
- */
- /*
- UGH UGH UGH
-
- This is a side effect, and there is no guarantee that this info is
- computed at a "sane" moment.
-
- (just spent some time tracking a bug that was caused by this info
- being written halfway:
-
- self_alignment_callback (*)
- -> child->relative_coordinate (self)
- -> break_alignment
- -> child->relative_coordinate (column)
-
- the last call incorporates the value that should've been computed
- in (*), but--of course-- is not yet.
-
- The result is that an offsets of align_elements_to_extents () are
- not compensated for, and spring_len is completely off.
-
- */
- column->set_grob_property ("extra-space",
- scm_cons (gh_double2scm (pre_space),
- gh_double2scm (spring_len)));
-
- column->set_grob_property ("stretch-distance",
- gh_cons (gh_double2scm (-dists[0]),
- gh_double2scm (stretch_distance)));
-}
-
-
-void
-Break_align_interface::set_interface (Grob*me)
-{
- Align_interface::set_interface (me);
- Align_interface::set_axis (me,X_AXIS);
-}
+++ /dev/null
-/*
- clef-item.cc -- implement Clef_item
-
- source file of the GNU LilyPond music typesetter
-
- (c) 1997--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
-*/
-
-
-#include "clef.hh"
-#include "string.hh"
-#include "molecule.hh"
-#include "item.hh"
-#include "font-interface.hh"
-
-/*
- FIXME: should use symbol for #'style.
-*/
-MAKE_SCHEME_CALLBACK (Clef,before_line_breaking,1);
-SCM
-Clef::before_line_breaking (SCM smob)
-{
- Item * s = unsmob_item (smob);
-
- SCM glyph = s->get_grob_property ("glyph-name");
-
- if (gh_string_p (glyph))
- {
- String str = ly_scm2string (glyph);
-
- if (to_boolean (s->get_grob_property ("non-default"))
- && s->break_status_dir () != RIGHT
- && !to_boolean (s->get_grob_property ("full-size-change")))
- {
- str += "_change";
- s->set_grob_property ("glyph-name", ly_str02scm (str.ch_C ()));
- }
- }
- else
- {
- s->suicide ();
- return SCM_UNSPECIFIED;
- }
-
- return SCM_UNSPECIFIED;
-}
-
-bool
-Clef::has_interface (Grob* me)
-{
- return me->has_interface (ly_symbol2scm ("clef-interface"));
-}
-
-
-void
-Clef::set_interface (Grob* me)
-{
- me->set_interface (ly_symbol2scm ("clef-interface"));
-}
-
-MAKE_SCHEME_CALLBACK (Clef,brew_molecule,1)
-SCM
-Clef::brew_molecule (SCM smob)
-{
- Grob * sc = unsmob_grob (smob);
- SCM glyph = sc->get_grob_property ("glyph-name");
- if (gh_string_p (glyph))
- {
- return Font_interface::get_default_font (sc)->find_by_name (String (ly_scm2string (glyph))).smobbed_copy ();
- }
- else
- {
- return SCM_EOL;
- }
-}
+++ /dev/null
-/*
- break-align-item.hh -- declare Break_align_item
-
- source file of the GNU LilyPond music typesetter
-
- (c) 1997--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
-*/
-
-
-#ifndef BREAK_ALIGN_ITEM_HH
-#define BREAK_ALIGN_ITEM_HH
-
-#include "item.hh"
-
-class Break_align_interface
-{
-public:
- DECLARE_SCHEME_CALLBACK (before_line_breaking, (SCM ));
- static void do_alignment (Grob*);
- static void set_interface (Grob*);
- static bool has_interface (Grob*);
- static void add_element (Grob*me, Grob*add);
- DECLARE_SCHEME_CALLBACK (alignment_callback, (SCM element, SCM axis));
- DECLARE_SCHEME_CALLBACK (self_align_callback, (SCM element, SCM axis));
-};
-#endif // BREAK_ALIGN_ITEM_HH
+++ /dev/null
-/*
- key-item.cc -- implement Key_item
-
- source file of the GNU LilyPond music typesetter
-
- (c) 1996--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
-
- keyplacement by Mats Bengtsson
-*/
-
-#include "item.hh"
-#include "key-item.hh"
-#include "molecule.hh"
-#include "paper-def.hh"
-#include "font-interface.hh"
-#include "staff-symbol-referencer.hh"
-#include "lookup.hh"
-
-/*
- FIXME: too much hardcoding here.
- */
-const int FLAT_TOP_PITCH=2; /* fes,ges,as and bes typeset in lower octave */
-const int SHARP_TOP_PITCH=4; /* ais and bis typeset in lower octave */
-
-
-/*
- FIXME: key-item should just get a list of (position, acc), and leave
- the thinking to other parties.
-
- - TODO: put this in Scheme
-
- - lots of values trivially shared (key doesn't change very
- often). Compute those once, and use that as cache for the rest.
-
-*/
-int
-alteration_pos (SCM what, int alter, int c0p)
-{
- if (gh_pair_p (what))
- return gh_scm2int (ly_car (what)) * 7 + gh_scm2int (ly_cdr (what)) + c0p;
-
- int p = gh_scm2int (what);
-
- // Find the c in the range -4 through 2
- int from_bottom_pos = c0p + 4;
- from_bottom_pos = from_bottom_pos%7;
- from_bottom_pos = (from_bottom_pos + 7)%7; // Precaution to get positive.
- int c0 = from_bottom_pos - 4;
-
-
- if ((alter <0 && ((p>FLAT_TOP_PITCH) || (p+c0>4)) && (p+c0>1))
- ||
- (alter >0 && ((p>SHARP_TOP_PITCH) || (p+c0>5)) && (p+c0>2)))
- {
- p -= 7; /* Typeset below c_position */
- }
- /* Provide for the four cases in which there's a glitch
- it's a hack, but probably not worth
- the effort of finding a nicer solution.
- --dl. */
- if (c0==2 && alter >0 && p==3)
- p -= 7;
- if (c0==-3 && alter>0 && p==-1)
- p += 7;
- if (c0==-4 && alter<0 && p==-1)
- p += 7;
- if (c0==-2 && alter<0 && p==-3)
- p += 7;
-
- return p + c0;
-}
-
-/*
- TODO
- - space the `natural' signs wider
- */
-MAKE_SCHEME_CALLBACK (Key_item,brew_molecule,1);
-SCM
-Key_item::brew_molecule (SCM smob)
-{
- Grob*me =unsmob_grob (smob);
-
- Real inter = Staff_symbol_referencer::staff_space (me)/2.0;
-
- SCM scm_style = me->get_grob_property ("style");
- String style;
- if (gh_symbol_p (scm_style))
- {
- style = ly_scm2string (scm_symbol_to_string (scm_style));
- }
- else
- {
- style = "";
- }
-
- SCM newas = me->get_grob_property ("new-accidentals");
- Molecule mol;
-
- SCM c0s = me->get_grob_property ("c0-position");
- int c0p=0;
- if (gh_number_p (c0s))
- c0p = gh_scm2int (c0s);
-
- /*
- SCM lists are stacks, so we work from right to left, ending with
- the cancellation signature.
- */
-
- for (SCM s = newas; gh_pair_p (s); s = ly_cdr (s))
- {
- SCM what = ly_caar (s);
- int alter = gh_scm2int (ly_cdar (s));
- int pos = alteration_pos (what, alter, c0p);
-
- Molecule m = Font_interface::get_default_font (me)->
- find_by_name (String ("accidentals-") + style + to_str (alter));
- m.translate_axis (pos * inter, Y_AXIS);
- mol.add_at_edge (X_AXIS, LEFT, m, 0);
- }
-
- Item *it = dynamic_cast<Item*> (me) ;
- if (it->break_status_dir () != RIGHT)
- {
- SCM old = me->get_grob_property ("old-accidentals");
-
- /*
- Add half a space between cancellation and key sig.
-
- As suggested by [Ross], p.148.
- */
- Interval x (0, inter);
- Interval y (0,0);
-
- mol.add_at_edge (X_AXIS, LEFT, Lookup::blank (Box (x,y)),0);
-
- Molecule natural;
- if (gh_pair_p (old))
- natural=Font_interface::get_default_font (me)->
- find_by_name (String ("accidentals-") + style + String ("0"));
-
- for (; gh_pair_p (old); old = ly_cdr (old))
- {
- SCM found = scm_assoc (ly_caar (old), newas);
- if (found == SCM_BOOL_F
- || ly_cdr (found) != ly_cdar (old))
- {
- SCM what = ly_caar (old);
- int alter = 0;
- int pos = alteration_pos (what, alter, c0p);
-
- Molecule m = natural;
- m.translate_axis (pos* inter, Y_AXIS);
-
- mol.add_at_edge (X_AXIS, LEFT, m, 0);
- }
- }
- }
-
- return mol.smobbed_copy ();
-}
-
-bool
-Key_item::has_interface (Grob*m)
-{
- return m && m->has_interface (ly_symbol2scm ("key-signature-interface"));
-}
-
-void
-Key_item::set_interface (Grob*m)
-{
- m->set_interface (ly_symbol2scm ("key-signature-interface"));
-}
+++ /dev/null
-/*
- spacing-spanner.cc -- implement Spacing_spanner
-
- source file of the GNU LilyPond music typesetter
-
- (c) 1999--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
-
- */
-#include "line-of-score.hh"
-#include "paper-score.hh"
-#include "paper-column.hh"
-#include "item.hh"
-#include "moment.hh"
-#include "note-spacing.hh"
-#include "misc.hh"
-#include "warn.hh"
-
-/*
- paper-column:
-
- right-neighbors = List of spacing-wish grobs that are close to the
- current column.
-
-
- left-neighbors = idem
-
- (TODO: property-doc these!)
-
- Don't be confused by right-items: each spacing wish can also contain
- a number of items, with which a spacing constraint may be kept. It's
- a little baroque, but it might come in handy later on?
-
- */
-
-class Third_spacing_spanner
-{
-public:
- static Real default_bar_spacing (Grob*,Grob*,Grob*,Moment) ;
- static Real note_spacing (Grob*,Grob*,Grob*,Moment) ;
- static Real get_duration_space (Grob*,Moment dur, Moment shortest) ;
-
- static void breakable_column_spacing (Item* l, Item *r);
- static void find_loose_columns () {}
- static void prune_loose_colunms (Link_array<Grob> *cols);
- static void find_loose_columns (Link_array<Grob> cols);
- static void set_explicit_neighbor_columns (Link_array<Grob> cols);
- static void set_implicit_neighbor_columns (Link_array<Grob> cols);
- static void do_measure (Grob*me,Link_array<Grob> *cols);
- DECLARE_SCHEME_CALLBACK (set_springs, (SCM ));
-};
-
-
-
-/*
- Return whether COL is fixed to its neighbors by some kind of spacing
- constraint.
-*/
-static bool
-loose_column (Grob *l, Grob *c, Grob *r)
-{
- SCM rns = c->get_grob_property ("right-neighbors");
- SCM lns = c->get_grob_property ("left-neighbors");
-
- /*
- If this column doesn't have a proper neighbor, we should really
- make it loose, but spacing it correctly is more than we can
- currently can handle.
-
- (this happens in the following situation:
-
- |
- | clef G
- *
-
- | | ||
- | | ||
- O O ||
-
-
- 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.
-
- )
-
- */
- if (!gh_pair_p (lns) || !gh_pair_p (rns))
- return false;
-
- Item * l_neighbor = dynamic_cast<Item*> (unsmob_grob (gh_car (lns)));
- Item * r_neighbor = dynamic_cast<Item*> (unsmob_grob (gh_car (rns)));
-
- if (!l_neighbor || !r_neighbor)
- return false;
-
- l_neighbor = l_neighbor->column_l();
- r_neighbor = dynamic_cast<Item*> (Note_spacing::right_column (r_neighbor));
-
- if (l == l_neighbor && r == r_neighbor)
- return false;
-
- if (!l_neighbor || !r_neighbor)
- return false;
-
- /*
- Only declare loose if the bounds make a little sense. This means
- 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))
- && (Paper_column::musical_b (r_neighbor) || Item::breakable_b (r_neighbor)))
- {
- return true;
- }
-
-
- /*
- If in doubt: we're not loose; the spacing engine should space for
- it, risking suboptimal spacing.
-
- (Otherwise, we might risk core dumps, and other weird stuff.)
-
-
- */
- return false;
-}
-
-/*
- Remove columns that are not tightly fitting from COLS. In the
- removed columns, set 'between-cols to the columns where it is in
- between.
-*/
-void
-Third_spacing_spanner::prune_loose_colunms (Link_array<Grob> *cols)
-{
- Link_array<Grob> newcols;
-
- for (int i=0; i < cols->size (); i++)
- {
- if (Item::breakable_b (cols->elem(i)) || Paper_column::musical_b (cols->elem (i)))
- {
- newcols.push (cols->elem(i));
- continue;
- }
-
- Grob *c = cols->elem(i);
- if (loose_column (cols->elem (i-1), c, cols->elem (i+1)))
- {
- SCM lns = c->get_grob_property ("left-neighbors");
- lns = gh_pair_p (lns) ? gh_car (lns) : SCM_BOOL_F;
-
- SCM rns = c->get_grob_property ("right-neighbors");
- rns = gh_pair_p (rns) ? gh_car (rns) : SCM_BOOL_F;
-
- /*
- Either object can be non existent, if the score ends
- prematurely.
- */
- rns = gh_car (unsmob_grob (rns)->get_grob_property ("right-items"));
- c->set_grob_property ("between-cols", gh_cons (lns,
- rns));
-
- /*
- Set distance constraints for loose columns
- */
- Drul_array<Grob*> next_door;
- next_door[LEFT] =cols->elem (i - 1);
- next_door[RIGHT] =cols->elem (i + 1);
- Direction d = LEFT;
- Drul_array<Real> dists(0,0);
-
- do
- {
- dists[d] = 0.0;
- Grob *lc = d == LEFT ? lc : c;
- Grob *rc = d == LEFT ? c : rc;
-
- for (SCM s = lc->get_grob_property ("spacing-wishes");
- gh_pair_p (s); s = gh_cdr (s))
- {
- Grob *sp = unsmob_grob (gh_car (s));
- if (Note_spacing::left_column (sp) != lc
- || Note_spacing::right_column (sp) != rc)
- continue;
-
- dists[d] = dists[d] >? Note_spacing::get_spacing (sp);
- }
- }
- while (flip (&d) != LEFT);
-
- Rod r;
- r.distance_f_ = dists[LEFT] + dists[RIGHT];
- r.item_l_drul_[LEFT] = dynamic_cast<Item*> (cols->elem(i-1));
- r.item_l_drul_[RIGHT] = dynamic_cast<Item*> (cols->elem (i+1));
-
- r.add_to_cols ();
- }
- else
- {
- newcols.push (c);
- }
- }
-
- *cols = newcols;
-}
-
-/*
- Set neighboring columns determined by the spacing-wishes grob property.
-*/
-void
-Third_spacing_spanner::set_explicit_neighbor_columns (Link_array<Grob> cols)
-{
- for (int i=0; i < cols.size(); i++)
- {
- SCM right_neighbors = SCM_EOL;
- int min_rank = 100000; // inf.
-
-
- SCM wishes= cols[i]->get_grob_property ("spacing-wishes");
- for (SCM s =wishes; gh_pair_p (s); s = gh_cdr (s))
- {
- Item * wish = dynamic_cast<Item*> (unsmob_grob (gh_car (s)));
-
- Item * lc = wish->column_l ();
- Grob * right = Note_spacing::right_column (wish);
-
- if (!right)
- continue;
-
- Item * rc = dynamic_cast<Item*> (right);
-
- int right_rank = Paper_column::rank_i (rc);
- int left_rank = Paper_column::rank_i (lc);
-
- /*
- update the left column.
- */
- if (right_rank <= min_rank)
- {
- if (right_rank < min_rank)
- right_neighbors =SCM_EOL;
-
- min_rank = right_rank;
- right_neighbors = gh_cons (wish->self_scm (), right_neighbors);
- }
-
- /*
- update the right column of the wish.
- */
- int maxrank = 0;
- SCM left_neighs = rc->get_grob_property ("left-neighbors");
- if (gh_pair_p (left_neighs)
- && unsmob_grob (gh_car (left_neighs)))
- {
- Item * it = dynamic_cast<Item*> (unsmob_grob (gh_car (left_neighs)));
- maxrank = Paper_column::rank_i (it->column_l());
- }
-
- if (left_rank >= maxrank)
- {
- if (left_rank > maxrank)
- left_neighs = SCM_EOL;
-
- left_neighs = gh_cons (wish->self_scm (), left_neighs);
- rc->set_grob_property ("left-neighbors", right_neighbors);
- }
- }
-
- if (gh_pair_p (right_neighbors))
- {
- cols[i]->set_grob_property ("right-neighbors", right_neighbors);
- }
- }
-}
-
-/*
- Set neighboring columns that have no left/right-neighbor set
- yet. Only do breakable non-musical columns, and musical columns.
-*/
-void
-Third_spacing_spanner::set_implicit_neighbor_columns (Link_array<Grob> cols)
-{
- for (int i = 0; i < cols.size (); i++)
- {
- Item * it = dynamic_cast<Item*>(cols[i]);
- if (!Item::breakable_b (it) && !Paper_column::musical_b (it))
- continue;
-
- // it->breakable || it->musical
-
- /*
- sloppy with typnig left/right-neighbors should take list, but paper-column found instead.
- */
- SCM ln = cols[i] ->get_grob_property ("left-neighbors");
- if (!gh_pair_p (ln) && i )
- {
- cols[i]->set_grob_property ("left-neighbors", gh_cons (cols[i-1]->self_scm(), SCM_EOL));
- }
-
- SCM rn = cols[i] ->get_grob_property ("right-neighbors");
- if (!gh_pair_p (rn) && i < cols.size () - 1)
- {
- cols[i]->set_grob_property ("right-neighbors", gh_cons (cols[i + 1]->self_scm(), SCM_EOL));
- }
- }
-}
-
-
-MAKE_SCHEME_CALLBACK (Third_spacing_spanner, set_springs,1);
-SCM
-Third_spacing_spanner::set_springs (SCM smob)
-{
- Grob *me = unsmob_grob (smob);
-
- Link_array<Grob> all (me->pscore_l_->line_l_->column_l_arr ()) ;
-
- set_explicit_neighbor_columns (all);
- prune_loose_colunms (&all);
- set_implicit_neighbor_columns (all);
-
- int j = 0;
- for (int i = 1; i < all.size (); i++)
- {
- Grob *sc = all[i];
- if (Item::breakable_b (sc))
- {
- Link_array<Grob> measure (all.slice (j, i+1));
- do_measure (me, &measure);
- j = i;
- }
- }
-
- return SCM_UNSPECIFIED;
-}
-
-
-void
-Third_spacing_spanner::do_measure (Grob*me, Link_array<Grob> *cols)
-{
- Moment shortest_in_measure;
-
- /*
- space as if this duration is present.
- */
- Moment base_shortest_duration = *unsmob_moment (me->get_grob_property ("maximum-duration-for-spacing"));
- shortest_in_measure.set_infinite (1);
-
- for (int i =0 ; i < cols->size (); i++)
- {
- if (Paper_column::musical_b (cols->elem (i)))
- {
- Moment *when = unsmob_moment (cols->elem (i)->get_grob_property ("when"));
-
- /*
- ignore grace notes for shortest notes.
- */
- if (when && when->grace_part_)
- continue;
-
- SCM st = cols->elem (i)->get_grob_property ("shortest-starter-duration");
- Moment this_shortest = *unsmob_moment (st);
- shortest_in_measure = shortest_in_measure <? this_shortest;
- }
- }
-
- Array<Spring> springs;
-
- for (int i= 0; i < cols->size () - 1; i++)
- {
- Item * l = dynamic_cast<Item*> (cols->elem (i));
- Item * r = dynamic_cast<Item*> (cols->elem (i+1));
-
- Paper_column * lc = dynamic_cast<Paper_column*> (l);
- Paper_column * rc = dynamic_cast<Paper_column*> (r);
-
- if (!Paper_column::musical_b (l))
- {
- breakable_column_spacing (l, r);
-
- /*
-
- The case that the right part is broken as well is rather
- rare, but it is possible, eg. with a single empty measure,
- or if one staff finishes a tad earlier than the rest.
-
- */
- Item *lb = l->find_prebroken_piece (RIGHT);
- Item *rb = r->find_prebroken_piece (LEFT);
-
- if (lb)
- breakable_column_spacing (lb,r);
-
- if (rb)
- breakable_column_spacing (l, rb);
- if (lb && rb)
- breakable_column_spacing (lb, rb);
-
- continue ;
- }
-
- Real note_space = note_spacing (me,lc, rc, shortest_in_measure <? base_shortest_duration);
- Real hinterfleisch = note_space;
- Real headwid = gh_scm2double (me->get_grob_property ("arithmetic-multiplier"));
-
- 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;
-
- 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));
-
- if (Note_spacing::left_column (wish) != lc
- || Note_spacing::right_column (wish) != rc)
- continue;
-
- /*
- This is probably a waste of time in the case of polyphonic
- music. */
- if (Note_spacing::has_interface (wish))
- {
- hinterfleisch = hinterfleisch >?
- ( - headwid +
-
- (note_space + Note_spacing::get_spacing (wish))
- *gh_scm2double (wish->get_grob_property ("space-factor"))
-
- + Note_spacing::stem_dir_correction (wish));
- }
- }
-
- if (hinterfleisch < 0)
- {
- // maybe should issue a programming error.
- hinterfleisch = note_space;
- }
- else
- stretch_distance -= headwid; // why?
-
- if (max_factor == 0.0)
- max_factor = 1.0;
-
- Spring s;
- s.distance_f_ = max_factor * hinterfleisch;
- s.strength_f_ = 1 / stretch_distance;
-
- s.item_l_drul_[LEFT] = l;
- s.item_l_drul_[RIGHT] = r;
-
- s.add_to_cols();
- if (r->find_prebroken_piece (LEFT))
- {
- s.item_l_drul_[RIGHT] = r->find_prebroken_piece(LEFT);
- s.add_to_cols();
- }
- }
-
-}
-
-
-/*
- Read hints from L (todo: R) and generate springs.
- */
-void
-Third_spacing_spanner::breakable_column_spacing (Item* l, Item *r)
-{
- Spring s;
-
- Real break_dist = 0.0;
- SCM espace = l->get_grob_property ("extra-space");
- if (gh_pair_p (espace))
- break_dist += gh_scm2double (ly_cdr (espace));
-
- if (!break_dist)
- break_dist = 1.0;
-
- Real break_stretch = 0.0;
-
- // todo: naming of "distance"
- espace = l->get_grob_property ("stretch-distance");
- if (gh_pair_p (espace))
- break_stretch += gh_scm2double (ly_cdr (espace));
-
- if (!break_stretch)
- break_stretch = 1.0;
-
- s.distance_f_ = break_dist;
- s.strength_f_ = 1/break_stretch;
- s.item_l_drul_[LEFT] = l;
- s.item_l_drul_[RIGHT] = r;
-
- s.add_to_cols ();
-}
-
-
-/**
- Get the measure wide ant for arithmetic spacing.
-
- @see
- John S. Gourlay. ``Spacing a Line of Music,'' Technical Report
- OSU-CISRC-10/87-TR35, Department of Computer and Information Science,
- The Ohio State University, 1987.
-
- */
-Real
-Third_spacing_spanner::get_duration_space (Grob*me, Moment d, Moment shortest)
-{
- Real log = log_2 (shortest.main_part_);
- Real k = gh_scm2double (me->get_grob_property ("arithmetic-basicspace"))
- - log;
-
- Rational compdur = d.main_part_ + d.grace_part_ /Rational (3);
-
- return (log_2 (compdur) + k) * gh_scm2double (me->get_grob_property ("arithmetic-multiplier"));
-}
-
-
-Real
-Third_spacing_spanner::note_spacing (Grob*me, Grob *lc, Grob *rc,
- Moment shortest)
-{
- Moment shortest_playing_len = 0;
- SCM s = lc->get_grob_property ("shortest-playing-duration");
-
-
- if (unsmob_moment (s))
- shortest_playing_len = *unsmob_moment (s);
-
- if (! shortest_playing_len.to_bool ())
- {
- programming_error ("can't find a ruling note at " + Paper_column::when_mom (lc).str ());
- shortest_playing_len = 1;
- }
-
- if (! shortest.to_bool ())
- {
- programming_error ("no minimum in measure at " + Paper_column::when_mom (lc).str ());
- shortest = 1;
- }
- Moment delta_t = Paper_column::when_mom (rc) - Paper_column::when_mom (lc);
- Real dist = 0.0;
-
- if (delta_t.main_part_)
- {
- dist = get_duration_space (me, shortest_playing_len, shortest);
- dist *= (double) (delta_t.main_part_ / shortest_playing_len.main_part_);
- }
- else if (delta_t.grace_part_)
- {
- dist = get_duration_space (me, shortest, shortest);
-
- Real grace_fact = 1.0;
- SCM gf = me->get_grob_property ("grace-space-factor");
- if (gh_number_p (gf))
- grace_fact = gh_scm2double (gf);
-
- dist *= grace_fact;
- }
-
-#if 0
- /*
- TODO: figure out how to space grace notes.
- */
-
- dist *=
- + grace_fact * (double) (delta_t.grace_part_ / shortest_playing_len.main_part_);
-
-
- Moment *lm = unsmob_moment (lc->get_grob_property ("when"));
- Moment *rm = unsmob_moment (rc->get_grob_property ("when"));
-
- if (lm && rm)
- {
- if (lm->grace_part_ && rm->grace_part_)
- dist *= 0.5;
- else if (!rm->grace_part_ && lm->grace_part_)
- dist *= 0.7;
- }
-#endif
-
- return dist;
-}
-