2004-09-11 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ * lily/*-engraver.cc: remove all Protected_scm objects to fix GC
+ errors with GUILE 1.7 CVS.
+
+ * lily/translator.cc (derived_mark): new function.
+
+ * lily/slur-scoring.cc (score_encompass): new penalty type:
+ variance penalty demerits slurs where one head/stem is much
+ closer to the slur than average.
+
+ * lily/tuplet-bracket.cc (print): use robust_relative_extent
+ iso. extent()
+ (calc_position_and_height): use robust_relative_extent(). This
+ fixes a couple of programming_errors
+
* input/regression/part-combine-mmrest-after-solo.ly (Module): new
file.
\version "2.3.7"
\paper {
raggedright = ##t
+% #(define debug-slur-scoring #t)
}
%% help lilypond-book
e4( dis4)
e4( dis4)
g='16( b d fis)
- \clef bass a=8[ e16(f] g[ a bes d,)] |
+ \clef bass a=8[ e16(f] g[ a bes d,)] s4 | \break
+
+ \clef treble
+ \relative c'' {
+ \slurDown f2( d4 f | g c a f | d c f2 | f1) |
+ }
+
}
virtual void process_acknowledged_grobs ();
virtual void finalize ();
+ virtual void derived_mark () const;
public:
- Protected_scm last_keysig_; // ugh.
+ SCM last_keysig_; // ugh.
/* Urgh. Since the accidentals depend on lots of variables, we have
to store all information before we can really create the
last_keysig_ = SCM_EOL;
}
+void
+Accidental_engraver::derived_mark () const
+{
+ scm_gc_mark (last_keysig_);
+}
+
void
Accidental_engraver::update_local_key_signature ()
{
virtual void acknowledge_grob (Grob_info);
virtual void stop_translation_timestep ();
virtual void finalize ();
+ virtual void derived_mark () const;
private:
void create_ambitus ();
Pitch_interval pitch_interval_;
bool is_typeset_;
int start_c0_;
- Protected_scm start_key_sig_;
+ SCM start_key_sig_;
};
+void
+Ambitus_engraver::derived_mark () const
+{
+ scm_gc_mark (start_key_sig_);
+}
+
void
Ambitus_engraver::create_ambitus ()
{
accidentals_[LEFT] = accidentals_[RIGHT] = 0;
group_ = 0;
is_typeset_ = false;
+ start_key_sig_ = SCM_EOL;
}
void
class Break_align_engraver : public Engraver
{
Item *align_;
- Protected_scm column_alist_;
+SCM column_alist_;
Item *left_edge_;
void add_to_group (SCM,Item*);
protected:
- virtual void finalize ();
virtual void acknowledge_grob (Grob_info i);
virtual void stop_translation_timestep ();
+ virtual void derived_mark () const;
void add_column (SCM);
public:
}
-void
-Break_align_engraver::finalize ()
-{
- column_alist_ = SCM_EOL;
-}
-
void
Break_align_engraver::stop_translation_timestep ()
{
align_ = 0;
}
+void
+Break_align_engraver::derived_mark () const
+{
+ scm_gc_mark (column_alist_);
+}
+
void
Break_align_engraver::acknowledge_grob (Grob_info inf)
{
virtual void process_music ();
virtual bool try_music (Music *);
virtual void finalize ();
+ virtual void derived_mark () const;
private:
void add_note (Music *);
Item* chord_name_;
Link_array<Music> notes_;
- Protected_scm last_chord_;
+ SCM last_chord_;
};
+
+
void
Chord_name_engraver::finalize ()
{
- last_chord_ = SCM_EOL;
+}
+
+void
+Chord_name_engraver::derived_mark() const
+{
+ scm_gc_mark (last_chord_);
}
Chord_name_engraver::Chord_name_engraver ()
SCM trans_names = get_translator_names (ops);
- Translator *g = get_translator (translator_group_type_);
- g = g->clone ();
+ Translator_group *g = dynamic_cast<Translator_group*>
+ (get_translator (translator_group_type_));
+ g = dynamic_cast<Translator_group*> (g->clone ());
SCM trans_list = SCM_EOL;
#include "lily-proto.hh"
#include "output-def.hh"
+#error
+
class Output_def : public Output_def
{
public:
{
public:
DECLARE_SCHEME_CALLBACK (after_line_breaking, (SCM ));
- static bool has_interface (Grob*);
+ static bool has_interface (Grob*);
};
#endif // CHORD_NAME_HH
virtual bool run_always () const;
virtual void process (Moment until);
- virtual void derived_mark ()const;
+ virtual void derived_mark () const;
virtual void construct_children ();
/**
Output_def (Output_def const&);
Output_def ();
- virtual void derived_mark ();
/*
variables.
virtual SCM get_simple_trans_list ();
virtual bool try_music (Music* req);
virtual void initialize ();
-};
+ Translator_group ();
+protected:
+ SCM simple_trans_list_;
+ friend class Context_def;
+ virtual void derived_mark () const;
+};
SCM names_to_translators (SCM namelist, Context*tg);
void recurse_over_translators (Context * c, Translator_method ptr, Direction);
DECLARE_SMOBS (Translator, dummy);
protected: // should be private.
Context * daddy_context_ ;
- SCM simple_trans_list_;
+ virtual void derived_mark () const;
+
friend class Context_def;
friend class Context;
};
virtual void acknowledge_grob (Grob_info);
virtual void process_music ();
virtual void stop_translation_timestep ();
+ virtual void derived_mark () const;
private:
Spanner *span_;
Spanner *finished_;
- Protected_scm last_ottavation_;
+ SCM last_ottavation_;
void typeset_all ();
};
+void
+Ottava_spanner_engraver::derived_mark () const
+{
+ scm_gc_mark (last_ottavation_ );
+}
Ottava_spanner_engraver::Ottava_spanner_engraver ()
{
if (mo->parent_)
scm_gc_mark (mo->parent_->self_scm ());
- mo->derived_mark ();
return mo->scope_;
}
-void
-Output_def::derived_mark ()
-{
-}
-
void
assign_context_def (Output_def * m, SCM transdef)
{
bool accept_music_type (Music*) const;
protected:
- virtual void derived_mark ();
+ virtual void derived_mark () const;
virtual void construct_children ();
virtual Moment pending_moment () const;
virtual void process (Moment);
void
-Quote_iterator::derived_mark ()
+Quote_iterator::derived_mark () const
{
scm_gc_mark (transposed_musics_ );
}
SCM copy = ly_deep_mus_copy (mus->self_scm ());
mus = unsmob_music (copy);
transposed_musics_ = scm_cons (copy, transposed_musics_);
+ scm_gc_unprotect_object (copy);
+
mus->transpose (diff);
}
virtual void stop_translation_timestep ();
virtual void finalize ();
virtual void initialize ();
- Protected_scm accumulator_;
+ virtual void derived_mark () const;
+ SCM accumulator_;
};
+void
+Recording_group_engraver::derived_mark () const
+{
+ Engraver_group_engraver::derived_mark();
+ scm_gc_mark (accumulator_);
+}
+
void
Recording_group_engraver::initialize ()
{
Recording_group_engraver::Recording_group_engraver ()
{
+ accumulator_ = SCM_EOL;
}
void
}
};
-/*
- TODO: put in details property.,
-
- use lowercase.
-*/
struct Slur_score_parameters
{
int region_size_;
Real max_slope_factor_;
Real extra_object_collision_;
Real accidental_collision_;
+
Real free_head_distance_;
Real extra_encompass_free_distance_;
+
+ Real head_slur_distance_max_ratio_;
+ Real head_slur_distance_factor_;
+
+
+
Slur_score_parameters (Grob*);
};
- curve around flag for y coordinate
- better scoring.
- short-cut: try a smaller region first.
- - collisions with accidentals
- - collisions with articulations (staccato, portato, sforzato, ...)
- handle non-visible stems better.
*/
struct Encompass_info
stem_ = 0.0;
head_ = 0.0;
}
+ Real get_point (Direction dir)
+ {
+ Interval y;
+ y.add_point (stem_);
+ y.add_point (head_);
+ return y[dir];
+ }
};
struct Bound_info
= get_detail (details, ly_symbol2scm ("accidental-collision"));
score_param->extra_encompass_free_distance_
= get_detail (details, ly_symbol2scm ("extra-encompass-free-distance"));
+ score_param->head_slur_distance_factor_
+ = get_detail (details, ly_symbol2scm ("head-slur-distance-factor"));
+ score_param->head_slur_distance_max_ratio_
+ = get_detail (details, ly_symbol2scm ("head-slur-distance-max-ratio"));
}
void
set_end_points (Grob *me)
{
-
-
-
Link_array<Grob> columns
= Pointer_group_interface__extract_grobs (me, (Grob *) 0, "note-columns");
#if DEBUG_SLUR_QUANTING
SCM inspect_quants = me->get_property ("inspect-quants");
if (to_boolean (me->get_paper ()
- ->lookup_variable (ly_symbol2scm ("debug-slur-quanting")))
+ ->lookup_variable (ly_symbol2scm ("debug-slur-scoring")))
&& ly_c_pair_p (inspect_quants))
{
Drul_array<Real> ins = ly_scm2interval (inspect_quants);
Real h_inf = staff_space * scm_to_double (me->get_property ("height-limit"));
for (int i = 0; i < scores->size(); i++)
{
- Bezier bez= get_bezier (me,
+ Bezier bez = get_bezier (me,
common,
score_param,
extremes,
(*scores)[i].attachment_, r_0, h_inf);
+
bez = avoid_staff_line (me, common, extremes, bez);
(*scores)[i].attachment_[LEFT] = bez.control_[0];
(*scores)[i].attachment_[RIGHT] = bez.control_[3];
* 5 * thick;
Real dy = (newp - p) * staff_space / 2.0;
-#if 0
- bez.translate (Offset (0, dy));
-#else
+
bez.control_[1][Y_AXIS] += dy;
bez.control_[2][Y_AXIS] += dy;
-
-#endif
}
}
return bez;
return scores;
}
+inline Real
+linear_interpolate (Real x, Real x1, Real x2, Real y1, Real y2)
+{
+ return (x2 - x) / (x2 - x1) * y1 +
+ (x - x1) / (x2 - x1) * y2 ;
+}
+
+
void
score_encompass (Grob *me, Grob *common[],
Slur_score_parameters *score_param,
for (int i = 0; i < scores->size (); i++)
{
- Bezier const &bez (scores->elem (i).curve_);
+ Slur_score &configuration = scores->elem_ref (i);
+ Bezier const &bez (configuration.curve_);
Real demerit = 0.0;
+
+ /*
+ Distances for heads that are between slur and line between
+ attachment points.
+ */
+ Array<Real> convex_head_distances;
+ Array<Real> edge_distances;
for (int j = 0; j < infos.size(); j++)
{
Real x = infos[j].x_;
bool r_edge = j==infos.size()-1;
bool edge = l_edge || r_edge;
- if (!(x < scores->elem (i).attachment_[RIGHT][X_AXIS]
- && x > scores->elem (i).attachment_[LEFT][X_AXIS]))
+
+ if (edge)
+ {
+ edge_distances.push (fabs (configuration.attachment_[l_edge ? LEFT : RIGHT][Y_AXIS]
+ - infos[j].get_point (dir)));
+ }
+
+
+ if (!(x < configuration.attachment_[RIGHT][X_AXIS]
+ && x > configuration.attachment_[LEFT][X_AXIS]))
continue;
Real y = bez.get_other_coordinate (X_AXIS, x);
{
Real head_dy = (y - infos[j].head_);
if (dir * head_dy < 0)
- demerit += score_param->head_encompass_penalty_;
+ {
+ demerit += score_param->head_encompass_penalty_;
+ convex_head_distances.push (0.0);
+ }
else
{
Real hd = (head_dy)
: score_param->head_encompass_penalty_;
hd = (hd >? 0)<? score_param->head_encompass_penalty_;
- demerit += hd;
+ demerit += hd;
}
- }
+
+ Real line_y = linear_interpolate (x,
+ configuration.attachment_[RIGHT][X_AXIS],
+ configuration.attachment_[LEFT][X_AXIS],
+ configuration.attachment_[RIGHT][Y_AXIS],
+ configuration.attachment_[LEFT][Y_AXIS]);
+
+ if (dir * (infos[j].get_point (dir) - line_y) > 0)
+ {
+ Real d = fabs (infos[j].get_point (dir) - y);
+ convex_head_distances.push (d);
+ }
+ }
+
+
+
if (dir * (y - infos[j].stem_) < 0)
{
}
}
+ Real variance_penalty = 0.0;
+
+ if (convex_head_distances.size())
+ {
+ Real avg_distance = 0.0;
+ Real min_dist = infinity_f;
+ for (int j = 0; j < convex_head_distances.size(); j++)
+ {
+ min_dist = min_dist <? convex_head_distances[j];
+ avg_distance += convex_head_distances[j];
+ }
+
+ /*
+ For slurs over 3 or 4 heads, the average distance is not a
+ good normalizer.
+ */
+ int n = convex_head_distances.size();
+ if (convex_head_distances.size() <= 2)
+ {
+ for (int j = 0; j < edge_distances.size(); j++)
+ {
+ avg_distance += edge_distances[j];
+ n++;
+ }
+ }
+
+ /*
+ TODO: maybe it's better to use (avgdist - mindist)*factor
+ as penalty.
+ */
+ avg_distance /= n;
+ variance_penalty = score_param->head_slur_distance_max_ratio_;
+ if (min_dist > 0.0)
+ variance_penalty = ((avg_distance / (min_dist +score_param->free_head_distance_)) - 1.0)
+ <? variance_penalty;
+
+ variance_penalty *= score_param->head_slur_distance_factor_;
+ }
#if DEBUG_SLUR_QUANTING
(*scores)[i].score_card_ += to_string ("C%.2f", demerit);
+ (*scores)[i].score_card_ += to_string ("D%.2f", variance_penalty);
#endif
- (*scores)[i].score_ += demerit;
+ (*scores)[i].score_ += demerit + variance_penalty;
}
}
Slur_score_parameters *score_param,
Drul_array<Bound_info> extremes,
Drul_array<Offset> attachments,
- Real r_0, Real h_inf)
+ Real r_0, Real h_inf
+ )
{
Link_array<Grob> encompasses
= Pointer_group_interface__extract_grobs (me, (Grob *)0, "note-columns");
SCM quant_score = me->get_property ("quant-score");
if (to_boolean (me->get_paper ()
- ->lookup_variable (ly_symbol2scm ("debug-slur-quanting")))
+ ->lookup_variable (ly_symbol2scm ("debug-slur-scoring")))
&& scm_is_string (quant_score))
{
String str;
virtual void create_audio_elements ();
private:
-Music* tempo_req_;
+ Music* tempo_req_;
Audio_tempo* audio_;
};
Link_array<Grob> now_heads_;
Link_array<Grob> heads_to_tie_;
Link_array<Grob> ties_;
- Protected_scm tie_start_definition_;
+ SCM tie_start_definition_;
Spanner * tie_column_;
protected:
virtual void stop_translation_timestep ();
+ virtual void derived_mark () const;
virtual void start_translation_timestep ();
virtual void acknowledge_grob (Grob_info);
virtual bool try_music (Music*);
event_ = 0;
last_event_ = 0;
tie_column_ = 0;
+ tie_start_definition_ = SCM_EOL;
+}
+
+void
+Tie_engraver::derived_mark () const
+{
+ scm_gc_mark (tie_start_definition_);
}
(tg->*ptr) ();
}
}
+
+Translator_group::Translator_group()
+{
+ simple_trans_list_ = SCM_EOL;
+}
+
+void
+Translator_group::derived_mark () const
+{
+ scm_gc_mark (simple_trans_list_);
+}
Translator *me = (Translator*) ly_cdr (s);
scm_puts ("#<Translator ", port);
scm_puts (classname (me), port);
- scm_display (me->simple_trans_list_, port);
-
scm_puts (" >", port);
return 1;
}
{
must_be_last_ = false;
self_scm_ = SCM_EOL;
- simple_trans_list_ = SCM_BOOL_F;
daddy_context_ =0;
smobify_self ();
}
Translator::mark_smob (SCM sm)
{
Translator * me = (Translator*) SCM_CELL_WORD_1 (sm);
- return me->simple_trans_list_;
+ me->derived_mark ();
+ return SCM_EOL;
}
SCM
return must_be_last_;
}
+void
+Translator::derived_mark () const
+{
+
+}
Direction dir = get_grob_direction (me);
Grob * lgr = get_x_bound_grob (columns[0], dir);
- Grob * rgr = get_x_bound_grob (columns.top (), dir);
- Real x0 = lgr->extent (commonx,X_AXIS)[LEFT];
- Real x1 = rgr->extent (commonx,X_AXIS)[RIGHT];
-
+ Grob * rgr = get_x_bound_grob (columns.top (), dir);
+
+ Real x0 = robust_relative_extent (lgr, commonx, X_AXIS)[LEFT];
+ Real x1 = robust_relative_extent (rgr, commonx, X_AXIS)[RIGHT];
Real w = x1 -x0;
SCM number = me->get_property ("text");
Grob * lgr = get_x_bound_grob (columns[0], dir);
Grob * rgr = get_x_bound_grob (columns.top (), dir);
- Real x0 = lgr->extent (commonx,X_AXIS)[LEFT];
- Real x1 = rgr->extent (commonx,X_AXIS)[RIGHT];
-
+ Real x0 = robust_relative_extent (lgr, commonx, X_AXIS)[LEFT];
+ Real x1 = robust_relative_extent (rgr, commonx, X_AXIS)[RIGHT];
/*
Slope.
/*
duh. magic.
-< */
+ */
offset = lp + dir * (0.5 + scm_to_double (me->get_property ("padding")));
dy = rp- lp;
}
(entry (list idx (1+ idx) distance)))
entry)))
(rods (map calc-rod (iota (1- no-systems))))
- (page-very-empty (> space-left (/ page-height 3)))
+ (page-very-empty? (> space-left (/ page-height 3)))
(result (ly:solve-spring-rod-problem
springs rods space
- ragged?))
- (force (car result))
+ (or page-very-empty? ragged?)))
+ (force (car (if page-very-empty?
+ (ly:solve-spring-rod-problem
+ springs rods space ragged?)
+ result)))
(positions
(map (lambda (y)
(+ y topskip))
(and (eq? #t (ly:output-def-lookup bookpaper 'raggedlastbottom))
last?)))
(page-height (page-height this-page-num last?))
-
(vertical-spacing (space-systems page-height current-lines ragged?))
(satisfied-constraints (car vertical-spacing))
(force (if satisfied-constraints satisfied-constraints 10000))
(extra-object-collision . 50)
(accidental-collision . 3)
(extra-encompass-free-distance . 0.3)
+ (head-slur-distance-max-ratio . 3)
+ (head-slur-distance-factor . 10)
))