From bf6cfba8705c5a4d76e5ab8c6669ea901d061ffb Mon Sep 17 00:00:00 2001 From: Joe Neeman Date: Fri, 14 Jan 2011 13:32:16 +0100 Subject: [PATCH] Optimizations for pure-height approximations. Since we end up querying the height of each VerticalAxisGroup multiple times for each line, cache the intermediate results. --- lily/axis-group-interface.cc | 46 ++++++++++++++++++++-------- lily/include/axis-group-interface.hh | 3 +- lily/include/spanner.hh | 5 +++ lily/spanner.cc | 27 ++++++++++++++++ 4 files changed, 67 insertions(+), 14 deletions(-) diff --git a/lily/axis-group-interface.cc b/lily/axis-group-interface.cc index 25952d6783..520d024516 100644 --- a/lily/axis-group-interface.cc +++ b/lily/axis-group-interface.cc @@ -90,7 +90,7 @@ Axis_group_interface::relative_group_extent (vector const &elts, } Interval -Axis_group_interface::cached_pure_height (Grob *me, int start, int end) +Axis_group_interface::sum_partial_pure_heights (Grob *me, int start, int end) { Interval iv = begin_of_line_pure_height (me, start); iv.unite (rest_of_line_pure_height (me, start, end)); @@ -99,27 +99,47 @@ Axis_group_interface::cached_pure_height (Grob *me, int start, int end) } Interval -Axis_group_interface::rest_of_line_pure_height (Grob *me, int start, int end) +Axis_group_interface::part_of_line_pure_height (Grob *me, bool begin, int start, int end) { + Spanner *sp = dynamic_cast (me); + SCM cache_symbol = begin + ? ly_symbol2scm ("begin-of-line-pure-height") + : ly_symbol2scm ("rest-of-line-pure-height"); + SCM cached = sp->get_cached_pure_property (cache_symbol, start, end); + if (scm_is_pair (cached)) + return robust_scm2interval (cached, Interval (0, 0)); + SCM adjacent_pure_heights = me->get_property ("adjacent-pure-heights"); + Interval ret; + + if (!scm_is_pair (adjacent_pure_heights)) + ret = Interval (0, 0); + else + { + SCM these_pure_heights = begin + ? scm_car (adjacent_pure_heights) + : scm_cdr (adjacent_pure_heights); - if (!scm_is_pair (adjacent_pure_heights) - || !scm_is_vector (scm_cdr (adjacent_pure_heights))) - return Interval (0, 0); + if (scm_is_vector (these_pure_heights)) + ret = combine_pure_heights (me, these_pure_heights, start, end); + else + ret = Interval (0, 0); + } - return combine_pure_heights (me, scm_cdr (adjacent_pure_heights), start, end); + sp->cache_pure_property (cache_symbol, start, end, ly_interval2scm (ret)); + return ret; } Interval Axis_group_interface::begin_of_line_pure_height (Grob *me, int start) { - SCM adjacent_pure_heights = me->get_property ("adjacent-pure-heights"); - - if (!scm_is_pair (adjacent_pure_heights) - || !scm_is_vector (scm_car (adjacent_pure_heights))) - return Interval (0, 0); + return part_of_line_pure_height (me, true, start, start + 1); +} - return combine_pure_heights (me, scm_car (adjacent_pure_heights), start, start+1); +Interval +Axis_group_interface::rest_of_line_pure_height (Grob *me, int start, int end) +{ + return part_of_line_pure_height (me, false, start, end); } Interval @@ -260,7 +280,7 @@ Axis_group_interface::relative_pure_height (Grob *me, int start, int end) we can assume additivity and cache things nicely. */ Grob *p = me->get_parent (Y_AXIS); if (p && Align_interface::has_interface (p)) - return Axis_group_interface::cached_pure_height (me, start, end); + return Axis_group_interface::sum_partial_pure_heights (me, start, end); Grob *common = unsmob_grob (me->get_object ("pure-Y-common")); extract_grob_set (me, "pure-relevant-grobs", elts); diff --git a/lily/include/axis-group-interface.hh b/lily/include/axis-group-interface.hh index fba715489d..fa66202096 100644 --- a/lily/include/axis-group-interface.hh +++ b/lily/include/axis-group-interface.hh @@ -48,9 +48,10 @@ struct Axis_group_interface Grob *common, Axis); static Interval relative_pure_height (Grob *me, int start, int end); static Interval combine_pure_heights (Grob *me, SCM, int, int); - static Interval cached_pure_height (Grob *me, int, int); + static Interval sum_partial_pure_heights (Grob *me, int, int); static Interval begin_of_line_pure_height (Grob *me, int); static Interval rest_of_line_pure_height (Grob *me, int, int); + static Interval part_of_line_pure_height (Grob *me, bool begin, int, int); static Skyline_pair skyline_spacing (Grob *me, vector elements); static void add_element (Grob *me, Grob *); diff --git a/lily/include/spanner.hh b/lily/include/spanner.hh index 834c1c8e6e..43468754ed 100644 --- a/lily/include/spanner.hh +++ b/lily/include/spanner.hh @@ -78,7 +78,12 @@ public: DECLARE_GROB_INTERFACE(); virtual System *get_system () const; + SCM get_cached_pure_property (SCM sym, int start, int end); + void cache_pure_property (SCM sym, int start, int end, SCM value); + protected: + SCM pure_property_cache_; + void set_my_columns (); virtual Grob *clone () const; virtual void do_break_processing (); diff --git a/lily/spanner.cc b/lily/spanner.cc index 3887797d90..f3d13c84f9 100644 --- a/lily/spanner.cc +++ b/lily/spanner.cc @@ -226,12 +226,14 @@ Spanner::Spanner (SCM s) { break_index_ = 0; spanned_drul_.set (0, 0); + pure_property_cache_ = SCM_UNDEFINED; } Spanner::Spanner (Spanner const &s) : Grob (s) { spanned_drul_.set (0, 0); + pure_property_cache_ = SCM_UNDEFINED; } Real @@ -327,6 +329,8 @@ Spanner::get_broken_left_end_align () const void Spanner::derived_mark () const { + scm_gc_mark (pure_property_cache_); + Direction d = LEFT; do if (spanned_drul_[d]) @@ -454,6 +458,29 @@ Spanner::kill_zero_spanned_time (SCM grob) return SCM_UNSPECIFIED; } +SCM +Spanner::get_cached_pure_property (SCM sym, int start, int end) +{ + // The pure property cache is indexed by (name start . end), where name is + // a symbol, and start and end are numbers referring to the starting and + // ending column ranks of the current line. + if (scm_hash_table_p (pure_property_cache_) == SCM_BOOL_F) + return SCM_UNDEFINED; + + SCM key = scm_cons (sym, scm_cons (scm_from_int (start), scm_from_int (end))); + return scm_hash_ref (pure_property_cache_, key, SCM_UNDEFINED); +} + +void +Spanner::cache_pure_property (SCM sym, int start, int end, SCM val) +{ + if (scm_hash_table_p (pure_property_cache_) == SCM_BOOL_F) + pure_property_cache_ = scm_c_make_hash_table (17); + + SCM key = scm_cons (sym, scm_cons (scm_from_int (start), scm_from_int (end))); + scm_hash_set_x (pure_property_cache_, key, val); +} + ADD_INTERFACE (Spanner, "Some objects are horizontally spanned between objects. For" " example, slurs, beams, ties, etc. These grobs form a subtype" -- 2.39.2