X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fspan-bar.cc;h=9a3312daa0f490cfd5c1cce4b5bd5368b3285d5b;hb=b6a3535923f893b4c593203c3421361ae02eba7c;hp=61f6b1b4e6816f986cd90658870fd9710e808f90;hpb=6ce61146edb1c36647b514778c29cdc9beedab6a;p=lilypond.git diff --git a/lily/span-bar.cc b/lily/span-bar.cc index 61f6b1b4e6..9a3312daa0 100644 --- a/lily/span-bar.cc +++ b/lily/span-bar.cc @@ -3,102 +3,236 @@ source file of the GNU LilyPond music typesetter - (c) 1997 Han-Wen Nienhuys + (c) 1997--2005 Han-Wen Nienhuys */ -#include "dimen.hh" #include "span-bar.hh" -#include "lookup.hh" -#include "symbol.hh" -#include "paper-def.hh" -#include "molecule.hh" -#include "vertical-align-elem.hh" + +#include "font-interface.hh" +#include "dimensions.hh" +#include "output-def.hh" +#include "stencil.hh" +#include "warn.hh" +#include "axis-group-interface.hh" +#include "bar-line.hh" +#include "grob.hh" +#include "pointer-group-interface.hh" void -Span_bar::add(Bar*b) +Span_bar::add_bar (Grob *me, Grob *b) { - b->spanned_i_ ++; - spanning_l_arr_.push(b); - add_dependency( b ); + Pointer_group_interface::add_grob (me, ly_symbol2scm ("elements"), b); + + me->add_dependency (b); } +MAKE_SCHEME_CALLBACK (Span_bar, print, 1); +/* Limitations/Bugs: -void -Span_bar::do_substitute_dependency(Score_elem*o, Score_elem*n) +(1) Elements from 'me->get_object ("elements")' must be +ordered according to their y coordinates relative to their common +axis group parent. Otherwise, the computation goes mad. + +(2) This method depends on bar_engraver not being removed from +staff context. If bar_engraver is removed, the size of the staff +lines is evaluated as 0, which results in a solid span bar line +with faulty y coordinate. */ + +/* This routine was originally by Juergen Reuter, but it was a on the + bulky side. Rewritten by Han-Wen. */ +SCM +Span_bar::print (SCM smobbed_me) { - Bar * bold = 0; - if (o->is_type_b(Bar::static_name() )) - bold = (Bar*)o->item(); - else - return; - - bold->spanned_i_ --; - Bar * b =0; - if (n && n->is_type_b(Bar::static_name() )) { - b = (Bar*)n->item(); - b->spanned_i_ ++; + Grob *me = unsmob_grob (smobbed_me); + extract_grob_set (me, "elements", elements); + Grob *refp = common_refpoint_of_array (elements, me, Y_AXIS); + + Span_bar::evaluate_glyph (me); + SCM glyph = me->get_property ("glyph"); + + /* glyph may not be a string, when ME is killed by Hara Kiri in + between. */ + if (!scm_is_string (glyph)) + return SCM_EOL; + + String glyph_string = ly_scm2string (glyph); + + /* compose span_bar_mol */ + Array extents; + Grob *model_bar = 0; + for (int i = elements.size (); i--;) + { + Grob *bar = elements[i]; + Interval ext = bar->extent (refp, Y_AXIS); + if (ext.is_empty ()) + continue; + + extents.push (ext); + model_bar = bar; } - - spanning_l_arr_.substitute( bold , b); + + if (!model_bar) + model_bar = me; + + extents.sort (&Interval::left_comparison); + + Stencil span_bar; + for (int i = 1; i < extents.size (); i++) + { + Interval prev_extent = extents[i - 1]; + Interval ext = extents[i]; + if (!prev_extent.is_empty ()) + { + Interval l (prev_extent [UP], + ext[DOWN]); + + if (l.is_empty ()) + { + /* There is overlap between the bar lines. Do nothing. */ + } + else + { + Stencil interbar = Bar_line::compound_barline (model_bar, + glyph_string, + l.length (), + false); + interbar.translate_axis (l.center (), Y_AXIS); + span_bar.add_stencil (interbar); + } + } + prev_extent = ext; + } + + span_bar.translate_axis (- me->relative_coordinate (refp, Y_AXIS), + Y_AXIS); + + return span_bar.smobbed_copy (); } -/* - A no-op if not yet output: the span_bar slavish follows what it spans - */ -void -Span_bar::translate_y(Real y) +MAKE_SCHEME_CALLBACK (Span_bar, width_callback, 2); +SCM +Span_bar::width_callback (SCM element_smob, SCM scm_axis) { - if (status() == OUTPUT) - Score_elem::translate_y(y); + Grob *se = unsmob_grob (element_smob); + (void) scm_axis; + + assert ((Axis) scm_to_int (scm_axis) == X_AXIS); + String gl = ly_scm2string (se->get_property ("glyph")); + + /* + urg. + */ + Stencil m = Bar_line::compound_barline (se, gl, 40 PT, false); + + return ly_interval2scm (m.extent (X_AXIS)); } -void -Span_bar::set(Vertical_align_element *a) +MAKE_SCHEME_CALLBACK (Span_bar, before_line_breaking, 1); +SCM +Span_bar::before_line_breaking (SCM smob) { - add_dependency( a ); + Grob *g = unsmob_grob (smob); + evaluate_empty (g); + evaluate_glyph (g); + + /* No need to call Bar_line::before_line_breaking (), because the info + in ELEMENTS already has been procced by + Bar_line::before_line_breaking (). */ + return SCM_UNSPECIFIED; } - -Interval -Span_bar::do_width() const +MAKE_SCHEME_CALLBACK (Span_bar, center_on_spanned_callback, 2); + +SCM +Span_bar::center_on_spanned_callback (SCM element_smob, SCM axis) { - return paper()->lookup_l()->bar(type_str_, 40 PT).dim.x; // ugh + Grob *me = unsmob_grob (element_smob); + (void) axis; + assert (scm_to_int (axis) == Y_AXIS); + Interval i (get_spanned_interval (me)); + + /* Bar_line::print delivers a barline of y-extent (-h/2, h/2), so + we have to translate ourselves to be in the center of the + interval that we span. */ + if (i.is_empty ()) + { + me->suicide (); + return scm_from_double (0.0); + } + + return scm_from_double (i.center ()); } + void -Span_bar::do_pre_processing() +Span_bar::evaluate_empty (Grob *me) { - if ( spanning_l_arr_.size () < 1) { - transparent_b_ = true; - empty_b_ =true; - } else { - if (type_str_ == "") - type_str_ = spanning_l_arr_[0]->type_str_; - if (type_str_ =="") { - transparent_b_=true; - empty_b_ = true; - } + /* TODO: filter all hara-kiried out of ELEMENS list, and then + optionally do suicide. Call this cleanage function from + center_on_spanned_callback () as well. */ + + extract_grob_set (me, "elements", elements); + if (elements.is_empty ()) + me->suicide (); +} + +void +Span_bar::evaluate_glyph (Grob *me) +{ + SCM gl = me->get_property ("glyph"); + + if (scm_is_string (gl)) + return; + + extract_grob_set (me, "elements", elements); + for (int i = elements.size (); + i-- && !scm_is_string (gl);) + gl = elements[i]->get_property ("glyph"); + + if (!scm_is_string (gl)) + { + me->suicide (); + return; } + + String type = ly_scm2string (gl); + if (type == "|:") + type = ".|"; + else if (type == ":|") + type = "|."; + else if (type == ":|:") + type = ".|."; + + gl = scm_makfrom0str (type.to_str0 ()); + if (scm_equal_p (me->get_property ("glyph"), gl) + != SCM_BOOL_T) + me->set_property ("glyph", gl); } -Symbol -Span_bar::get_bar_sym(Real dy) const +Interval +Span_bar::get_spanned_interval (Grob *me) { - return paper()->lookup_l()->bar(type_str_, dy); + return ly_scm2interval (Axis_group_interface::group_extent_callback + (me->self_scm (), scm_from_int (Y_AXIS))); } -Molecule* -Span_bar::brew_molecule_p()const +MAKE_SCHEME_CALLBACK (Span_bar, get_bar_size, 1); +SCM +Span_bar::get_bar_size (SCM smob) { - Interval y; - for (int i=0; i < spanning_l_arr_.size(); i++) - y.unite( spanning_l_arr_[i]->height() ); - Symbol s = get_bar_sym(y.length()); - Molecule*output = new Molecule(Atom(s)); - output->translate_y ( y[-1] ); - - return output; + Grob *me = unsmob_grob (smob); + Interval iv (get_spanned_interval (me)); + if (iv.is_empty ()) + { + /* This happens if the bars are hara-kiried from under us. */ + me->suicide (); + return scm_from_double (-1); + } + return scm_from_double (iv.length ()); } -IMPLEMENT_STATIC_NAME(Span_bar); -IMPLEMENT_IS_TYPE_B1(Span_bar,Bar); +ADD_INTERFACE (Span_bar, "span-bar-interface", + "A bar line that spanned between other barlines. This interface is " + " used for bar lines that connect different staves.", + "elements"); +