--- /dev/null
+
+\score {
+\notes < \context Staff { \clef "G^8"; s1 s1 s1 }
+ \context Staff = CC { c1 c c } >
+
+\paper {
+\translator {
+ \HaraKiriStaffContext
+}}
+}
--- /dev/null
+\score
+{
+ \context StaffGroup = a <
+ \context PianoStaff = b <
+ \context Staff = "c" \notes\relative c'' { b1 \break b }
+ \context Staff = "d" \notes\relative c'' { b1 \break b }
+ >
+ >
+
+ \paper {
+ indent=100.0\mm;
+ linewidth=150.0\mm;
+ \translator
+ {
+ \StaffContext
+ \consists "Staff_margin_engraver";
+ numberOfStaffLines = #1
+ marginScriptPadding = #10 % urg: this is in PT
+ instrument = #"Foo"
+ instr = #"Foo"
+ }
+ }
+}
--- /dev/null
+\score
+{
+ \context StaffGroup = a <
+ \context PianoStaff = b <
+ \context Staff = "c" \notes\relative c'' { b1 \break b }
+ \context Staff = "d" \notes\relative c'' { b1 \break b }
+ >
+ >
+
+ \paper {
+ indent=100.0\mm;
+ linewidth=150.0\mm;
+ \translator
+ {
+ \StaffContext
+ \consists "Staff_margin_engraver";
+ numberOfStaffLines = #1
+ marginScriptPadding = #30 % urg: this is in PT
+ instrument = #"Foo"
+ instr = #"Bar"
+ }
+ }
+}
#include "hash-table-iter.hh"
#include "dimension-cache.hh"
-void
-Align_element::after_line_breaking()
+/*
+ This callback is set in the children of the align element. It does
+ not compute anything, but a side effect of a->do_side_processing ()
+ is that the elements are placed correctly. */
+Real
+Align_element::alignment_callback (Dimension_cache const *c)
{
- if (axis () == Y_AXIS)
- do_side_processing ();
+ Axis ax = c->axis ();
+ Score_element * sc = c->element_l ()->parent_l (ax);
+ Align_element * a = dynamic_cast<Align_element*> (sc);
+ if (a && a->get_elt_property ("alignment-done") == SCM_UNDEFINED)
+ {
+ a->do_side_processing (ax);
+ }
+ return 0.0;
}
void
-Align_element::before_line_breaking ()
+Align_element::add_element (Score_element* s)
{
- if (axis () == X_AXIS)
- do_side_processing ();
+ s->add_offset_callback (alignment_callback, axis ());
+ Axis_group_element::add_element (s);
}
+/*
+ Hairy function to put elements where they should be. Can be tweaked
+ from the outside by setting minimum-space and extra-space in its
+ children */
void
-Align_element::do_side_processing ()
+Align_element::do_side_processing (Axis a)
{
+ set_elt_property ("alignment-done", SCM_BOOL_T);
+
SCM d = get_elt_property ("stacking-dir");
Direction stacking_dir = gh_number_p(d) ? to_dir (d) : CENTER;
if (!stacking_dir)
Link_array<Score_element> all_elts (elem_l_arr ());
for (int i=0; i < all_elts.size(); i++)
{
- Interval y = all_elts[i]->extent(axis ()) + all_elts[i]->relative_coordinate (this, axis ());
+ Interval y = all_elts[i]->extent(a) + all_elts[i]->relative_coordinate (this, a);
if (!y.empty_b())
{
Score_element *e =dynamic_cast<Score_element*>(all_elts[i]);
}
}
+
+ Interval threshold = Interval (0, Interval::infinity ());
+ SCM thr = get_elt_property ("threshold");
+ if (gh_pair_p (thr))
+ {
+ threshold[SMALLER] = gh_scm2double (gh_car (thr));
+ threshold[BIGGER] = gh_scm2double (gh_cdr (thr));
+ }
+
Real where_f=0;
for (int i=0 ; i < elems.size(); i++)
{
if (i)
{
- dy = (dy >? threshold_interval_[SMALLER] )
- <? threshold_interval_[BIGGER];
+ dy = (dy >? threshold[SMALLER] )
+ <? threshold[BIGGER];
}
-
where_f += stacking_dir * dy;
- elems[i]->translate_axis (where_f, axis ());
+ elems[i]->translate_axis (where_f, a);
}
}
-Align_element::Align_element()
-{
- threshold_interval_ = Interval (0, Interval::infinity ());
-}
int
Align_element::get_count (Score_element*s)const
Axis
Align_element::axis () const
{
- return axes_[0];
+ return Axis (gh_scm2int (gh_car (get_elt_property ("axes"))));
}
void
Align_element::set_axis (Axis a)
{
- set_axes (a,a);
+ set_axes (a, a);
}
#include "dimension-cache.hh"
#include "group-interface.hh"
-Link_array<Score_element>
-Axis_group_element::get_extra_dependencies() const
-{
- Link_array<Score_element> e(elem_l_arr ());
- return e;
-}
-
Link_array<Score_element>
Axis_group_element::elem_l_arr () const
{
Axis_group_element::Axis_group_element()
{
- axes_[0] = (Axis)-1 ;
- axes_[1] = (Axis)-1 ;
-
set_elt_property ("elements", SCM_EOL);
set_elt_property ("transparent", SCM_BOOL_T);
}
void
Axis_group_element::set_axes (Axis a1, Axis a2)
{
- axes_[0] = a1 ;
- axes_[1] = a2 ;
+ SCM ax = gh_cons (gh_int2scm (a1), SCM_EOL);
+ if (a1 != a2)
+ ax= gh_cons (gh_int2scm (a2), ax);
+
+
+ set_elt_property ("axes", ax);
+
if (a1 != X_AXIS && a2 != X_AXIS)
set_empty (X_AXIS);
if (a1 != Y_AXIS && a2 != Y_AXIS)
}
+bool
+Axis_group_element::axis_b (Axis a )const
+{
+ return dim_cache_[a]->extent_callback_l_ == extent_callback;
+}
+
void
Axis_group_element::add_element (Score_element *e)
{
used_b_ =true;
e->used_b_ = true;
-
- for (int i = 0; i < 2; i++)
+
+ for (SCM ax = get_elt_property ("axes"); ax != SCM_EOL ; ax = gh_cdr (ax))
{
- if (!e->parent_l (axes_[i]))
- e->set_parent (this, axes_[i]);
+ Axis a = (Axis) gh_scm2int (gh_car (ax));
+
+ if (!e->parent_l (a))
+ e->set_parent (this, a);
}
Group_interface gi (this);
gi.add_element (e);
+
+ add_dependency (e);
}
set_elt_property ("stacking-dir" , gh_int2scm (RIGHT));
set_axis (X_AXIS);
- dim_cache_[X_AXIS]->off_callbacks_.push (Side_position_interface::aligned_on_self);
+ add_offset_callback (Side_position_interface::aligned_on_self, X_AXIS);
}
g->set_parent (this, X_AXIS);
g->set_elt_property ("self-alignment-X", gh_int2scm (0));
- g->dim_cache_[X_AXIS]->off_callbacks_.push (Side_position_interface::aligned_on_self);
- g->dim_cache_[X_AXIS]->off_callbacks_.push (Side_position_interface::centered_on_parent);
-
+ g->add_offset_callback (Side_position_interface::aligned_on_self, X_AXIS);
+ g->add_offset_callback (Side_position_interface::centered_on_parent, X_AXIS);
+
g->set_elt_property ("direction", octave_dir);
add_dependency (g); // just to be sure.
Align_element * align = dynamic_cast<Align_element*> (common);
if (align && align->axis() == Y_AXIS)
{
- if (align->threshold_interval_[MIN] !=
- align->threshold_interval_[MAX])
+ SCM threshold = align->get_elt_property ("threshold");
+ if (!gh_pair_p (threshold)
+ || !scm_equal_p (gh_car (threshold), gh_cdr (threshold)))
warning (_ ("minVerticalAlign != maxVerticalAlign: cross staff spanners may be broken"));
- interstaff = align->threshold_interval_[MIN];
+ interstaff = 0.0;
+ if (gh_pair_p (threshold))
+ interstaff = gh_scm2double (gh_car (threshold));
Score_element const * span_refpoint = span;
while (span_refpoint->parent_l (Y_AXIS) != common)
Dimension_cache::Dimension_cache (Dimension_cache const &d)
{
init();
- callback_l_ = d.callback_l_;
+ extent_callback_l_ = d.extent_callback_l_;
basic_offset_ = d.basic_offset_;
extra_offset_ = d.extra_offset_;
off_valid_b_ = d.off_valid_b_;
void
Dimension_cache::init()
{
- callback_l_ =0;
+ extent_callback_l_ =0;
basic_offset_ =0.0;
extra_offset_ =0.0;
{
Interval r;
Dimension_cache *nc = ((Dimension_cache*)this);
- if (!callback_l_)
+ if (!extent_callback_l_)
{
nc->dim_.set_empty ();
}
else if (!valid_b_)
{
- nc->dim_= (*callback_l_ ) (nc);
+ nc->dim_= (*extent_callback_l_ ) (nc);
nc->valid_b_ = true;
}
void
Dimension_cache::set_callback (Dim_cache_callback c)
{
- callback_l_ =c;
+ extent_callback_l_ =c;
}
Which side to align? -1: left side, 0: centered (around
center_l_ if not nil, or around center of width), 1: right side
- *****
-
- align-dir: deprecate! Use Side_pos_interface::self_align
-
*/
class Align_element : public virtual Axis_group_element {
public:
- Interval threshold_interval_ ;
-
Axis axis () const;
-
- Align_element ();
+
void set_axis (Axis);
int get_count (Score_element*)const;
+ void add_element (Score_element *);
+ static Real alignment_callback (Dimension_cache const *);
protected:
- virtual void after_line_breaking () ;
- virtual void before_line_breaking ();
- virtual void do_side_processing ();
+ virtual void do_side_processing (Axis);
+
};
#endif // VERTICAL_ALIGN_ITEM_HH
*/
class Axis_group_element : public virtual Score_element
{
- /// modify fields of E for removal.
- void do_remove (Score_element*e);
-
protected:
- virtual Link_array<Score_element> get_extra_dependencies() const;
virtual Link_array<Score_element> elem_l_arr() const;
static Interval extent_callback (Dimension_cache const*);
public:
- Axis axes_[2];
-
void add_element (Score_element*);
-
+ bool axis_b (Axis) const;
Axis_group_element ();
void set_axes (Axis,Axis);
--- /dev/null
+/*
+ dimension-cache-callback.hh -- declare
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+
+ */
+
+#ifndef DIMENSION_CACHE_CALLBACK_HH
+#define DIMENSION_CACHE_CALLBACK_HH
+
+class Dimension_cache;
+typedef Interval (*Dim_cache_callback)(Dimension_cache const *);
+typedef Real (*Offset_cache_callback)(Dimension_cache const *);
+
+#endif /* DIMENSION_CACHE_CALLBACK_HH */
+
#include "real.hh"
#include "lily-proto.hh"
#include "parray.hh"
+#include "dimension-cache-callback.hh"
-class Dimension_cache;
-typedef Interval (*Dim_cache_callback)(Dimension_cache const *);
-typedef Real (*Offset_cache_callback)(Dimension_cache const *);
/**
Adminstration of offset dimension info.
friend class Score_element;
void init ();
-public:
Array<Offset_cache_callback> off_callbacks_;
/**
What to call to find extent. Nil means empty.
*/
- Dim_cache_callback callback_l_;
+public:
+ Dim_cache_callback extent_callback_l_;
static Interval point_dimension_callback (Dimension_cache const* );
Axis axis () const;
Real get_offset () const;
struct Key_performer;
struct Keyword;
struct Keyword_table;
+struct Left_edge_item;
struct Lily_stream;
struct Line_group_engraver;
struct Line_of_score;
if (get_elt_property ("self-alignment-X") != SCM_UNDEFINED
&& !dim_cache_[X_AXIS]->off_callback_l_)
{
- dim_cache_[X_AXIS]->off_callbacks_.push (Side_position_interface::aligned_on_self);
+ add_offset_callback (Side_position_interface::aligned_on_self,X_AXIS);
}
if (get_elt_property ("self-alignment-Y") != SCM_UNDEFINED
&& !dim_cache_[X_AXIS]->off_callback_l_)
{
- dim_cache_[Y_AXIS]->set_offset_callback (Side_position_interface::aligned_on_self);
+ add_offset_callback (Side_position_interface::aligned_on_self, Y_AXIS);
}
#endif
assert (status_i_!= busy);
status_i_= busy;
- Link_array<Score_element> dependency_arr =
- Group_interface__extract_elements (this, (Score_element*)0, "dependencies");
-
- for (int i=0; i < dependency_arr.size(); i++)
- dependency_arr[i]->calculate_dependencies (final, busy, funcptr);
+ for (SCM d= get_elt_property ("dependencies"); d != SCM_EOL; d = gh_cdr (d))
+ {
+ unsmob_element (gh_car (d))
+ ->calculate_dependencies (final, busy, funcptr);
+ }
- Link_array<Score_element> extra (get_extra_dependencies());
- for (int i=0; i < extra.size(); i++)
- extra[i]->calculate_dependencies (final, busy, funcptr);
-
(this->*funcptr)();
status_i_= final;
}
}
}
-Link_array<Score_element>
-Score_element::get_extra_dependencies() const
-{
- Link_array<Score_element> empty;
- return empty;
-}
-
bool
Score_element::linked_b() const
{
void
Score_element::set_empty (Axis a)
{
- dim_cache_[a]->callback_l_ =0;
+ dim_cache_[a]->extent_callback_l_ =0;
}
bool
Score_element::empty_b (Axis a)const
{
- return !dim_cache_[a]->callback_l_;
+ return !dim_cache_[a]->extent_callback_l_;
}
Interval
return classname (this);
}
+void
+Score_element::add_offset_callback (Offset_cache_callback cb, Axis a)
+{
+ dim_cache_[a]->off_callbacks_.push (cb);
+}
+
+bool
+Score_element::has_offset_callback_b (Offset_cache_callback cb, Axis a)const
+{
+ for (int i= dim_cache_[a]->off_callbacks_.size (); i--;)
+ {
+ if (dim_cache_[a]->off_callbacks_[i] == cb)
+ return true;
+ }
+ return false;
+}
void
Score_element::set_parent (Score_element *g, Axis a)
if (elt_l_->get_elt_property ("side-support") == SCM_UNDEFINED)
elt_l_->set_elt_property ("side-support" ,SCM_EOL);
- elt_l_->dim_cache_[a]->off_callbacks_.push (aligned_side);
+ elt_l_->add_offset_callback (aligned_side, a);
}
void
Side_position_interface::set_quantised (Axis a)
{
- Dimension_cache * c = elt_l_->dim_cache_[a];
-
- c->off_callbacks_.push (quantised_position);
+ elt_l_->add_offset_callback (quantised_position, a);
}
Axis
Side_position_interface::get_axis () const
{
- Dimension_cache * c = elt_l_->dim_cache_[X_AXIS];
- for (int i=0 ; i < c->off_callbacks_.size();i ++)
- if (c->off_callbacks_[i] == side_position
- ||c->off_callbacks_[i] == aligned_side)
- return X_AXIS;
+ if (elt_l_->has_offset_callback_b (&side_position, X_AXIS)
+ || elt_l_->has_offset_callback_b (&aligned_side , X_AXIS))
+ return X_AXIS;
return Y_AXIS;
void
Vertical_align_engraver::do_removal_processing()
{
- SCM dist (get_property ("maxVerticalAlign"));
- if (gh_number_p(dist))
- {
- valign_p_->threshold_interval_[BIGGER] = gh_scm2double (dist);
- }
-
- dist = get_property ("minVerticalAlign");
- if (gh_number_p(dist))
- {
- valign_p_->threshold_interval_[SMALLER] = gh_scm2double (dist);
- }
+ SCM min = get_property ("maxVerticalAlign");
+ SCM max = get_property ("minVerticalAlign");
+ if (gh_number_p (min) || gh_number_p (max))
+ {
+ min = gh_number_p (min) ? min : gh_double2scm (0.0);
+ max = gh_number_p (max) ? max : gh_double2scm (infinity_f);
+
+ valign_p_->set_elt_property ("threshold",
+ gh_cons (min,max));
+ }
valign_p_->set_bound(RIGHT,get_staff_info().command_pcol_l ());
typeset_element (valign_p_);
valign_p_ =0;
Axis_group_element * elt = dynamic_cast<Axis_group_element *> (i.elem_l_);
- return sz > 1 && elt && elt->axes_[0] == Y_AXIS && !elt->parent_l (Y_AXIS);
+ return sz > 1 && elt && !elt->parent_l (Y_AXIS) && elt->axis_b (Y_AXIS);
}
void
\type "Engraver_group_engraver";
\name Voice;
- dynamicPadding = #5.0
+ dynamicPadding = #2.0
Generic_property_list = #generic-voice-properties
\consists "Output_property_engraver";
% \consists "Score_priority_engraver";
\consists "Break_align_engraver";
breakAlignOrder = #'(
+ "Left_edge_item"
"Span_bar"
"Breathing_sign"
"Clef_item"
#'Stem_tremolo::beam-width = 1.5 * \quartwidth ;
+#'Left_edge_item::visibility-lambda = #begin-of-line-visible
#'Clef_item::visibility-lambda = #begin-of-line-visible
#'Key_item::visibility-lambda = #begin-of-line-visible
#'Breathing_sign::visibility-lambda = #begin-of-line-invisible
;; (Measured in staff space)
(define space-alist
'(
+ (("" "Left_edge_item") . (minimum-space -15.0))
(("" "Clef_item") . (minimum-space 1.0))
(("" "Staff_bar") . (minimum-space 0.0))
(("" "Clef_item") . (minimum-space 1.0))
# override EndLilyPondOutput, since @tex is done
# in a sandbox, you can't do \input lilyponddefs at the
# top of the document.
+
+# should also support fragment in
+
'output-all': r"""@tex
\catcode`\@=12
\input lilyponddefs
\catcode`\@=0
@end tex
@html
+<p>
<img src=%s.png>
@end html
""",