Re: Getting the height of a system.

2006-06-08 Thread Han-Wen Nienhuys

Joe Neeman schreef:

On Thu, 2006-06-08 at 09:05 +1000, Joe Neeman wrote:

Anyway, here's another try. Same ChangeLog as before


After your last email, I've removed the changes to
Item::handle_prebroken_dependencies and changed axis-group-interface.cc.
I'm only attaching the part of axis-group-interface.cc with the most
recent changes.




+  vectorGrob* relevant_elts;
+  SCM is_relevant = ly_lily_module_constant (pure-relevant);



+   if (piece  to_boolean (scm_apply_1 (is_relevant, 
piece-self_scm (), SCM_EOL)))
+ relevant_elts.push_back (elts[i]);


Looks good. small question: why is pure-relevant coming in from Scheme 
C++ seems more applicable? It's not a user serviceable part, is it?


--

Han-Wen Nienhuys - [EMAIL PROTECTED] - http://www.xs4all.nl/~hanwen

LilyPond Software Design
 -- Code for Music Notation
http://www.lilypond-design.com



___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Getting the height of a system.

2006-06-08 Thread Joe Neeman
On Thu, 2006-06-08 at 17:18 +0200, Han-Wen Nienhuys wrote:
 Joe Neeman schreef:
  On Thu, 2006-06-08 at 09:05 +1000, Joe Neeman wrote:
  Anyway, here's another try. Same ChangeLog as before
  
  After your last email, I've removed the changes to
  Item::handle_prebroken_dependencies and changed axis-group-interface.cc.
  I'm only attaching the part of axis-group-interface.cc with the most
  recent changes.
  
 
  +  vectorGrob* relevant_elts;
  +  SCM is_relevant = ly_lily_module_constant (pure-relevant);
 
  +   if (piece  to_boolean (scm_apply_1 (is_relevant, 
  piece-self_scm (), SCM_EOL)))
  + relevant_elts.push_back (elts[i]);
 
 Looks good. small question: why is pure-relevant coming in from Scheme 
 C++ seems more applicable? It's not a user serviceable part, is it?

Just because the Y-XX-conversions and pure-Y-XX lists are in scheme, and
I thought it was nicer not to make them public, but to provide public
accessing functions instead. I can move it to C++, though, if you'd
prefer.

Now that I go back to look at it, I see that the lists are actually
public. That's fixed now.



___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Getting the height of a system.

2006-06-08 Thread Han-Wen Nienhuys

Joe Neeman schreef:
Looks good. small question: why is pure-relevant coming in from Scheme 
C++ seems more applicable? It's not a user serviceable part, is it?


Just because the Y-XX-conversions and pure-Y-XX lists are in scheme, and
I thought it was nicer not to make them public, but to provide public
accessing functions instead. I can move it to C++, though, if you'd
prefer.

Now that I go back to look at it, I see that the lists are actually
public. That's fixed now.


It's not that important, but all the jumping back and forth between C++ 
and scheme makes things a bit difficult to understand.


--

Han-Wen Nienhuys - [EMAIL PROTECTED] - http://www.xs4all.nl/~hanwen

LilyPond Software Design
 -- Code for Music Notation
http://www.lilypond-design.com



___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Getting the height of a system.

2006-06-07 Thread Han-Wen Nienhuys

Joe Neeman schreef:

Did my previous mail make it to the list? I never saw it... but anyway,
here's an update


sorry, it was on my todo list, but your patch got caught up in other stuff.


make web still works and there are no detected formatting changes.


Very very cool. Does this complete the optimal pagebreaking, or does the 
dynamic programming part need more work now?



+
+  if (scm_is_number (dy_scm))
+{
+  Real dy = scm_to_double (dy_scm) * robust_scm2dir (me-get_property 
(stacking-dir), DOWN);
+  Real pos = 0;
+  for (vsize i = 0; i  all_grobs.size (); i++)
+   {
+ if (all_grobs[i] == ch)
+   return pos;
+ if (!Hara_kiri_group_spanner::has_interface (all_grobs[i])
+ || !Hara_kiri_group_spanner::request_suicide (all_grobs[i], 
start, end))
+   pos += dy;
+   }
 }
+  else


don't understand: aren't you missing a return? pos isn't used any further.



+  vsize start_brk = VPOS;
+  vsize end_brk = VPOS;


brk - index


+
+  /* The only time a parent is allowed to affect its children's Y-offset is if
+ it has align-interface */
+  Grob *p = get_parent (Y_AXIS);


I think you know, but this happens in some other cases as well. Mostly 
all grobs that support the positioning-done property.




+  if (pure  a != Y_AXIS)
+programming_error (_f (tried to get pure X-offset));


don't mark programming errors as translatable. They're supposed to be 
read by programmers, not users.



+bool
+Hara_kiri_group_spanner::request_suicide (Grob *me, int start, int end)
+{
+  if (!to_boolean (me-get_property (remove-empty)))
+return false;



+  SCM important = me-get_property (important-columns);


Clever!


+  for (vsize i = 0; i  worth.size (); i++)
+   {
+ Item *it = dynamic_castItem* (worth[i]);
+ if (it)
+   {
+ vsize col = Paper_column::get_rank (it-get_column ());
+ important_cols.resize (max (important_cols.size (), col+1));
+ important_cols[col] = 1;
+   }
+   }


This looks dodgy. The resize call may introduce uninitialized data. 
Isn't it easier to sort the items-worth-living by column-rank and then 
insert False for any spans that are skipped by items-worth-living?


Considering naming, I'd use important-column-ranks.

Please use true iso. 1.


+
+  /* if we end up suiciding, our Y-axis-parent won't get the correct
+Y-extent unless we add our child to it */
+  Grob *p = unsmob_grob (get_object (axis-group-parent-Y));
+  if (p)
+   Axis_group_interface::add_element (p, dolly);


This will result in duplicate elements in the axis-group-parent-Y after 
line breaking.  Isn't it possible to handle this in any of the relevant 
pure_XX functions?


--

Han-Wen Nienhuys - [EMAIL PROTECTED] - http://www.xs4all.nl/~hanwen

LilyPond Software Design
 -- Code for Music Notation
http://www.lilypond-design.com



___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Getting the height of a system.

2006-06-07 Thread Joe Neeman
On Wed, 2006-06-07 at 10:25 +0200, Han-Wen Nienhuys wrote:
 Joe Neeman schreef:
  Did my previous mail make it to the list? I never saw it... but anyway,
  here's an update
 
 sorry, it was on my todo list, but your patch got caught up in other stuff.

That's fine, it's just that for some reason I didn't get a copy of my
mail back so I wasn't sure if it sent properly.

 
  make web still works and there are no detected formatting changes.
 
 Very very cool. Does this complete the optimal pagebreaking, or does the 
 dynamic programming part need more work now?

I revisited the algorithm a few weeks ago, so it should be fairly clean.
There is some more functionality I would like to do though:

- tandem page/line breaking with page turns (done)
- tandem page/line breaking ignoring page turns (todo)
- tandem page/line breaking with fixed number of pages (todo)
- line, then page breaking ignoring page turns (todo)

I've tried to refactor the existing code so the other methods won't take
much code. Once I've done the last one, I can rip out the existing page
breaker. I'll post my code here before I do all that, though. It's quite
capable of peacefully coexisting with the current page breaker.

 
  +
  +  if (scm_is_number (dy_scm))
  +{
  +  Real dy = scm_to_double (dy_scm) * robust_scm2dir (me-get_property 
  (stacking-dir), DOWN);
  +  Real pos = 0;
  +  for (vsize i = 0; i  all_grobs.size (); i++)
  +   {
  + if (all_grobs[i] == ch)
  +   return pos;
  + if (!Hara_kiri_group_spanner::has_interface (all_grobs[i])
  + || !Hara_kiri_group_spanner::request_suicide (all_grobs[i], 
  start, end))
  +   pos += dy;
  +   }
   }
  +  else
 
 don't understand: aren't you missing a return? pos isn't used any further.
but it has a different value when we go through the loop again. I could
initialise pos to (-dy) and put the return at the end of the loop if it
would be clearer.

 
 
  +  vsize start_brk = VPOS;
  +  vsize end_brk = VPOS;
 
 brk - index
sure

 
  +
  +  /* The only time a parent is allowed to affect its children's Y-offset 
  is if
  + it has align-interface */
  +  Grob *p = get_parent (Y_AXIS);
 
 I think you know, but this happens in some other cases as well. Mostly 
 all grobs that support the positioning-done property.
I didn't know when that when I wrote the comment, though ;) I'll rewrite
the comment.

 
 
  +  if (pure  a != Y_AXIS)
  +programming_error (_f (tried to get pure X-offset));
 
 don't mark programming errors as translatable. They're supposed to be 
 read by programmers, not users.
sure

  +  for (vsize i = 0; i  worth.size (); i++)
  +   {
  + Item *it = dynamic_castItem* (worth[i]);
  + if (it)
  +   {
  + vsize col = Paper_column::get_rank (it-get_column ());
  + important_cols.resize (max (important_cols.size (), col+1));
  + important_cols[col] = 1;
  +   }
  +   }
 
 This looks dodgy. The resize call may introduce uninitialized data. 
 Isn't it easier to sort the items-worth-living by column-rank and then 
 insert False for any spans that are skipped by items-worth-living?
Probably. I'll rethink this one.

 
 Considering naming, I'd use important-column-ranks.
 
 Please use true iso. 1.
OK

 
  +
  +  /* if we end up suiciding, our Y-axis-parent won't get the correct
  +Y-extent unless we add our child to it */
  +  Grob *p = unsmob_grob (get_object (axis-group-parent-Y));
  +  if (p)
  +   Axis_group_interface::add_element (p, dolly);
 
 This will result in duplicate elements in the axis-group-parent-Y after 
 line breaking.  Isn't it possible to handle this in any of the relevant 
 pure_XX functions?

I don't think so. For example, a BarNumber gets created and added to
System-object_alist_-elements. Since a mid-line BarNumber is
invisible, the original grob sucides in
Item::handle_prebroken_dependencies. By the time System-pure_extent
gets called, there are no live BarNumbers in the elements list, so none
of the pure_XX functions even get to see a BarNumber.

I suppose I could move the change into
Item::handle_prebroken_dependencies -- if we want to suicide an original
grob but the broken pieces are still potentially visible, add them to
the Y-axis-parent. Would that be better?



___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Getting the height of a system.

2006-06-07 Thread Han-Wen Nienhuys

Joe Neeman schreef:

+  /* if we end up suiciding, our Y-axis-parent won't get the correct
+Y-extent unless we add our child to it */
+  Grob *p = unsmob_grob (get_object (axis-group-parent-Y));
+  if (p)
+   Axis_group_interface::add_element (p, dolly);
This will result in duplicate elements in the axis-group-parent-Y after 
line breaking.  Isn't it possible to handle this in any of the relevant 
pure_XX functions?


I don't think so. For example, a BarNumber gets created and added to
System-object_alist_-elements. Since a mid-line BarNumber is
invisible, the original grob sucides in
Item::handle_prebroken_dependencies. By the time System-pure_extent
gets called, there are no live BarNumbers in the elements list, so none
of the pure_XX functions even get to see a BarNumber.


I'm not sure I understand. The BarNumber won't be live, but it should 
still be in the 'elements grob_array, or am I missing something?


--

Han-Wen Nienhuys - [EMAIL PROTECTED] - http://www.xs4all.nl/~hanwen

LilyPond Software Design
 -- Code for Music Notation
http://www.lilypond-design.com



___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Getting the height of a system.

2006-06-07 Thread Han-Wen Nienhuys

Joe Neeman schreef:

make web still works and there are no detected formatting changes.
Very very cool. Does this complete the optimal pagebreaking, or does the 
dynamic programming part need more work now?


I revisited the algorithm a few weeks ago, so it should be fairly clean.
There is some more functionality I would like to do though:

- tandem page/line breaking with page turns (done)
- tandem page/line breaking ignoring page turns (todo)
- tandem page/line breaking with fixed number of pages (todo)
- line, then page breaking ignoring page turns (todo)

I've tried to refactor the existing code so the other methods won't take
much code. Once I've done the last one, I can rip out the existing page
breaker. I'll post my code here before I do all that, though. It's quite
capable of peacefully coexisting with the current page breaker.


OK, but this already should give new functionality, right? If so we can 
merge the code. We should have one or two of testcases though. Either 
real-world pieces or some artificial scores.


--

Han-Wen Nienhuys - [EMAIL PROTECTED] - http://www.xs4all.nl/~hanwen

LilyPond Software Design
 -- Code for Music Notation
http://www.lilypond-design.com



___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Getting the height of a system.

2006-06-07 Thread Joe Neeman
Anyway, here's another try. Same ChangeLog as before
Index: ChangeLog
===
RCS file: /sources/lilypond/lilypond/ChangeLog,v
retrieving revision 1.5101
diff -u -r1.5101 ChangeLog
--- ChangeLog	7 Jun 2006 22:01:13 -	1.5101
+++ ChangeLog	7 Jun 2006 22:54:54 -
@@ -1,3 +1,39 @@
+2006-06-08  Joe Neeman  [EMAIL PROTECTED]
+
+	* scm/paper-system.scm (paper-system-annotate): also annotate the
+	estimated pure-Y-extent
+
+	* scm/define-grobs.scm: add pure-Y-extent and pure-Y-offset functions
+
+	* lily/system.cc (break_into_pieces): set the estimated height
+	of each child system
+
+	* lily/stem.cc (pure_height): new pure-Y-extent callback
+
+	* lily/staff-symbol-referencer.cc (callback): don't destroy
+	the staff-position property
+
+	* lily/hara-kiri-group-spanner.cc (request_suicide): split
+	consider_suicide into two functions
+
+	* lily/constrained-breaking.cc (resize): use the new pure
+	callbacks to estimate the height of a system
+
+	* lily/axis-group-interface.cc (pure_group_height): new
+	side-effect-free VerticalAxisGroup height-callback
+
+	* lily/align-interface.cc (get_extents_aligned_translates):
+	split align_elements_to_extents into two functions
+	(get_pure_child_y_translation): new function
+
+	* lily/grob.cc: new functions for pure-Y-extent and pure-Y-offset
+
+	* lily/item.cc: new functions pure_is_visible and spanned_rank_iv
+
+	* lily/paper-score.cc: cache break_indices and columns
+
+	* lily/side-position-interface.cc: new pure-Y-extent callbacks
+	
 2006-06-07  Graham Percival  [EMAIL PROTECTED]
 
 	* input/test/ add-staccato.ly, add-text-script.ly,
Index: lily/align-interface.cc
===
RCS file: /sources/lilypond/lilypond/lily/align-interface.cc,v
retrieving revision 1.97
diff -u -r1.97 align-interface.cc
--- lily/align-interface.cc	19 Feb 2006 00:14:59 -	1.97
+++ lily/align-interface.cc	7 Jun 2006 22:54:55 -
@@ -14,6 +14,7 @@
 #include hara-kiri-group-spanner.hh
 #include grob-array.hh
 #include international.hh
+#include warn.hh
 
 /*
   TODO: for vertical spacing, should also include a rod  spring
@@ -145,8 +146,11 @@
   align_to_fixed_distance ().
 */
 
-void
-Align_interface::align_elements_to_extents (Grob *me, Axis a)
+vectorReal
+Align_interface::get_extents_aligned_translates (Grob *me,
+		 vectorGrob* const all_grobs,
+		 Axis a,
+		 bool pure, int start, int end)
 {
   Spanner *me_spanner = dynamic_castSpanner * (me);
 
@@ -156,7 +160,7 @@
 {
   line_break_details = me_spanner-get_bound (LEFT)-get_property (line-break-system-details);
 
-  if (!me-get_system ())
+  if (!me-get_system ()  !pure)
 	me-warning (_ (vertical alignment called before line-breaking.\n
 			Only do cross-staff spanners with PianoStaff.));
 
@@ -171,10 +175,9 @@
   vectorInterval dims;
   vectorGrob* elems;
 
-  extract_grob_set (me, elements, all_grobs);
   for (vsize i = 0; i  all_grobs.size (); i++)
 {
-  Interval y = all_grobs[i]-extent (me, a);
+  Interval y = all_grobs[i]-maybe_pure_extent (all_grobs[i], a, pure, start, end);
   if (!y.is_empty ())
 	{
 	  Grob *e = dynamic_castGrob * (all_grobs[i]);
@@ -245,24 +248,68 @@
   if (translates.size ())
 {
   Real w = translates[0];
+
+  if (scm_is_number (align))
+	center_offset = total.linear_combination (scm_to_double (align));
+
   for  (vsize i = 0, j = 0; j  all_grobs.size (); j++)
 	{
 	  if (i  elems.size ()  all_grobs[j] == elems[i])
 	w = translates[i++];
-	  all_translates.push_back (w);
+	  all_translates.push_back (w - center_offset);
 	}
+}
+  return all_translates;
+}
 
-  /*
-	FIXME: uncommenting freaks out the Y-alignment of
-	line-of-score.
-  */
-  if (scm_is_number (align))
-	center_offset = total.linear_combination (scm_to_double (align));
+void
+Align_interface::align_elements_to_extents (Grob *me, Axis a)
+{
+  extract_grob_set (me, elements, all_grobs);
 
+  vectorReal translates = get_extents_aligned_translates (me, all_grobs, a, false, 0, 0);
+  if (translates.size ())
   for (vsize j = 0; j  all_grobs.size (); j++)
-	all_grobs[j]-translate_axis (all_translates[j] - center_offset, a);
+	all_grobs[j]-translate_axis (translates[j], a);
+}
+
+Real
+Align_interface::get_pure_child_y_translation (Grob *me, Grob *ch, int start, int end)
+{
+  extract_grob_set (me, elements, all_grobs);
+  SCM dy_scm = me-get_property (forced-distance);
+
+  if (scm_is_number (dy_scm))
+{
+  Real dy = scm_to_double (dy_scm) * robust_scm2dir (me-get_property (stacking-dir), DOWN);
+  Real pos = 0;
+  for (vsize i = 0; i  all_grobs.size (); i++)
+	{
+	  if (all_grobs[i] == ch)
+	return pos;
+	  if (!Hara_kiri_group_spanner::has_interface (all_grobs[i])
+	  || !Hara_kiri_group_spanner::request_suicide (all_grobs[i], start, end))
+	pos += dy;
+	}
 }
+  else
+{
+  vectorReal translates = 

Re: Getting the height of a system.

2006-06-07 Thread Joe Neeman
On Thu, 2006-06-08 at 09:05 +1000, Joe Neeman wrote:
 Anyway, here's another try. Same ChangeLog as before

After your last email, I've removed the changes to
Item::handle_prebroken_dependencies and changed axis-group-interface.cc.
I'm only attaching the part of axis-group-interface.cc with the most
recent changes.

@@ -89,3 +190,47 @@
   return ly_interval2scm (r - my_coord);
 }
 
+SCM
+Axis_group_interface::pure_group_height (Grob *me, int start, int end)
+{
+  Grob *common = unsmob_grob (me-get_object (common-refpoint-of-elements));
+
+  if (!common)
+{
+  extract_grob_set (me, elements, elts);
+
+  vectorGrob* relevant_elts;
+  SCM is_relevant = ly_lily_module_constant (pure-relevant);
+
+  for (vsize i = 0; i  elts.size (); i++)
+	{
+	  if (to_boolean (scm_apply_1 (is_relevant, elts[i]-self_scm (), SCM_EOL)))
+	relevant_elts.push_back (elts[i]);
+
+	  Item *it = dynamic_castItem* (elts[i]);
+	  Direction d = LEFT;
+	  if (it)
+	do
+	  {
+		Item *piece = it-find_prebroken_piece (d);
+		if (piece  to_boolean (scm_apply_1 (is_relevant, piece-self_scm (), SCM_EOL)))
+		  relevant_elts.push_back (elts[i]);
+	  }
+	while (flip (d) != LEFT);
+	}
+
+  common = common_refpoint_of_array (relevant_elts, me, Y_AXIS);
+  me-set_object (common-refpoint-of-elements, common-self_scm ());
+
+  SCM ga_scm = Grob_array::make_array ();
+  Grob_array *ga = unsmob_grob_array (ga_scm);
+  ga-set_array (relevant_elts);
+  me-set_object (pure-relevant-elements, ga_scm);
+}
+
+  extract_grob_set (me, pure-relevant-elements, elts);
+  Real my_coord = me-relative_coordinate (common, Y_AXIS);
+  Interval r (relative_pure_height (me, elts, common, start, end, true));
+
+  return ly_interval2scm (r - my_coord);
+}
+___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Getting the height of a system.

2006-06-06 Thread Joe Neeman
Did my previous mail make it to the list? I never saw it... but anyway,
here's an update

On Mon, 2006-05-22 at 20:58 +1000, Joe Neeman wrote:
 On Mon, 2006-05-22 at 10:57 +0200, Han-Wen Nienhuys wrote:
  
  Does this patch already work for determining system heights, or is just 
  the beginning of the work? How much more must done?

The attached patch seems to be pretty accurate and reasonably fast. It
supports dynamics, rehearsal marks, bar lines and a bunch of other
things that tend to appear above and below the staff. It also annotates
the estimated extent.

The only things I know of that it doesn't support are accidentals and
slurs. I have a couple examples where a flat sticks off the top of the
staff, but I don't think it's really a big deal.

make web still works and there are no detected formatting changes.

2006-06-07  Joe Neeman  [EMAIL PROTECTED]

* scm/paper-system.scm (paper-system-annotate): also annotate the
estimated pure-Y-extent

* scm/define-grobs.scm: add pure-Y-extent and pure-Y-offset functions

* lily/system.cc (break_into_pieces): set the estimated height
of each child system

* lily/stem.cc (pure_height): new pure-Y-extent callback

* lily/staff-symbol-referencer.cc (callback): don't destroy
the staff-position property

* lily/hara-kiri-group-spanner.cc (request_suicide): split
consider_suicide into two functions

* lily/constrained-breaking.cc (resize): use the new pure
callbacks to estimate the height of a system

* lily/axis-group-interface.cc (pure_group_height): new
side-effect-free VerticalAxisGroup height-callback

* lily/align-interface.cc (get_extents_aligned_translates):
split align_elements_to_extents into two functions
(get_pure_child_y_translation): new function

* lily/grob.cc: new functions for pure-Y-extent and pure-Y-offset

* lily/item.cc: new functions pure_is_visible and spanned_rank_iv

* lily/paper-score.cc: cache break_indices and columns

* lily/side-position-interface.cc: new pure-Y-extent callbacks
Index: ChangeLog
===
RCS file: /sources/lilypond/lilypond/ChangeLog,v
retrieving revision 1.5095
diff -u -r1.5095 ChangeLog
--- ChangeLog	6 Jun 2006 20:34:41 -	1.5095
+++ ChangeLog	7 Jun 2006 01:25:31 -
@@ -1,3 +1,39 @@
+2006-06-07  Joe Neeman  [EMAIL PROTECTED]
+
+	* scm/paper-system.scm (paper-system-annotate): also annotate the
+	estimated pure-Y-extent
+
+	* scm/define-grobs.scm: add pure-Y-extent and pure-Y-offset functions
+
+	* lily/system.cc (break_into_pieces): set the estimated height
+	of each child system
+
+	* lily/stem.cc (pure_height): new pure-Y-extent callback
+
+	* lily/staff-symbol-referencer.cc (callback): don't destroy
+	the staff-position property
+
+	* lily/hara-kiri-group-spanner.cc (request_suicide): split
+	consider_suicide into two functions
+
+	* lily/constrained-breaking.cc (resize): use the new pure
+	callbacks to estimate the height of a system
+
+	* lily/axis-group-interface.cc (pure_group_height): new
+	side-effect-free VerticalAxisGroup height-callback
+
+	* lily/align-interface.cc (get_extents_aligned_translates):
+	split align_elements_to_extents into two functions
+	(get_pure_child_y_translation): new function
+
+	* lily/grob.cc: new functions for pure-Y-extent and pure-Y-offset
+
+	* lily/item.cc: new functions pure_is_visible and spanned_rank_iv
+
+	* lily/paper-score.cc: cache break_indices and columns
+
+	* lily/side-position-interface.cc: new pure-Y-extent callbacks
+	
 2006-06-06  Erik Sandberg  [EMAIL PROTECTED]
 
 	* ly/music-functions-init.ly: Updated \overrideProperty to use the
Index: lily/align-interface.cc
===
RCS file: /sources/lilypond/lilypond/lily/align-interface.cc,v
retrieving revision 1.97
diff -u -r1.97 align-interface.cc
--- lily/align-interface.cc	19 Feb 2006 00:14:59 -	1.97
+++ lily/align-interface.cc	7 Jun 2006 01:25:32 -
@@ -14,6 +14,7 @@
 #include hara-kiri-group-spanner.hh
 #include grob-array.hh
 #include international.hh
+#include warn.hh
 
 /*
   TODO: for vertical spacing, should also include a rod  spring
@@ -145,8 +146,11 @@
   align_to_fixed_distance ().
 */
 
-void
-Align_interface::align_elements_to_extents (Grob *me, Axis a)
+vectorReal
+Align_interface::get_extents_aligned_translates (Grob *me,
+		 vectorGrob* const all_grobs,
+		 Axis a,
+		 bool pure, int start, int end)
 {
   Spanner *me_spanner = dynamic_castSpanner * (me);
 
@@ -156,7 +160,7 @@
 {
   line_break_details = me_spanner-get_bound (LEFT)-get_property (line-break-system-details);
 
-  if (!me-get_system ())
+  if (!me-get_system ()  !pure)
 	me-warning (_ (vertical alignment called before line-breaking.\n
 			Only do cross-staff spanners with PianoStaff.));
 
@@ -171,10 +175,9 @@
   

Re: Getting the height of a system.

2006-06-02 Thread Joe Neeman
On Mon, 2006-05-22 at 20:58 +1000, Joe Neeman wrote:
 On Mon, 2006-05-22 at 10:57 +0200, Han-Wen Nienhuys wrote:
  Joe Neeman schreef:
   In that case, you could get the approximate height of one broken system 
   in logarithmic time.
  
   Here's a first attempt at doing this. It isn't complete or well-tested
   yet.
Here's my second attempt. I think it is feature-complete. It's also
reasonably fast. I have successfully used it to page-break the entire
Haydn Op 76 string quartets and it seems to be accurate enough. Web
makes successfully, although I haven't yet dug through the regression
tests to make sure they're OK.

Things still to do:
- remove the debugging messages
- remove the code that is commented out
- review the caching (I implemented caching little by little while
benchmarking, but I don't know if my later efforts made my earlier ones
obsolete)
- maybe move most of Grob::pure_height and
Grob::pure_relative_y_coordinate to Scheme (It was originally in scheme,
but I moved it to C++ for speed reasons that might not matter any more)

How does it look?
Index: lily/align-interface.cc
===
RCS file: /sources/lilypond/lilypond/lily/align-interface.cc,v
retrieving revision 1.97
diff -u -r1.97 align-interface.cc
--- lily/align-interface.cc	19 Feb 2006 00:14:59 -	1.97
+++ lily/align-interface.cc	3 Jun 2006 02:10:06 -
@@ -14,6 +14,7 @@
 #include hara-kiri-group-spanner.hh
 #include grob-array.hh
 #include international.hh
+#include warn.hh
 
 /*
   TODO: for vertical spacing, should also include a rod  spring
@@ -145,8 +146,11 @@
   align_to_fixed_distance ().
 */
 
-void
-Align_interface::align_elements_to_extents (Grob *me, Axis a)
+vectorReal
+Align_interface::get_extents_aligned_translates (Grob *me,
+		 vectorGrob* const all_grobs,
+		 Axis a,
+		 bool pure, int start, int end)
 {
   Spanner *me_spanner = dynamic_castSpanner * (me);
 
@@ -156,7 +160,7 @@
 {
   line_break_details = me_spanner-get_bound (LEFT)-get_property (line-break-system-details);
 
-  if (!me-get_system ())
+  if (!me-get_system ()  !pure)
 	me-warning (_ (vertical alignment called before line-breaking.\n
 			Only do cross-staff spanners with PianoStaff.));
 
@@ -171,10 +175,9 @@
   vectorInterval dims;
   vectorGrob* elems;
 
-  extract_grob_set (me, elements, all_grobs);
   for (vsize i = 0; i  all_grobs.size (); i++)
 {
-  Interval y = all_grobs[i]-extent (me, a);
+  Interval y = all_grobs[i]-maybe_pure_extent (all_grobs[i], a, pure, start, end);
   if (!y.is_empty ())
 	{
 	  Grob *e = dynamic_castGrob * (all_grobs[i]);
@@ -245,24 +248,50 @@
   if (translates.size ())
 {
   Real w = translates[0];
+
+  if (scm_is_number (align))
+	center_offset = total.linear_combination (scm_to_double (align));
+
   for  (vsize i = 0, j = 0; j  all_grobs.size (); j++)
 	{
 	  if (i  elems.size ()  all_grobs[j] == elems[i])
 	w = translates[i++];
-	  all_translates.push_back (w);
+	  all_translates.push_back (w - center_offset);
 	}
+}
+  return all_translates;
+}
 
-  /*
-	FIXME: uncommenting freaks out the Y-alignment of
-	line-of-score.
-  */
-  if (scm_is_number (align))
-	center_offset = total.linear_combination (scm_to_double (align));
+void
+Align_interface::align_elements_to_extents (Grob *me, Axis a)
+{
+  extract_grob_set (me, elements, all_grobs);
 
+  vectorReal translates = get_extents_aligned_translates (me, all_grobs, a, false, 0, 0);
+  if (translates.size ())
   for (vsize j = 0; j  all_grobs.size (); j++)
-	all_grobs[j]-translate_axis (all_translates[j] - center_offset, a);
+	all_grobs[j]-translate_axis (translates[j], a);
+}
+
+Real
+Align_interface::get_pure_child_y_translation (Grob *me, Grob *ch, int start, int end)
+{
+  extract_grob_set (me, elements, all_grobs);
+  vectorReal translates = get_extents_aligned_translates (me, all_grobs, Y_AXIS, true, start, end);
+
+  if (translates.size ())
+{
+  for (vsize i = 0; i  all_grobs.size (); i++)
+	if (all_grobs[i] == ch)
+	  return translates[i];
 }
+  else
+return 0;
+
+  programming_error (_ (tried to get a translation for something that isn't my child));
+  return 0;
 }
+
 Axis
 Align_interface::axis (Grob *me)
 {
Index: lily/axis-group-interface.cc
===
RCS file: /sources/lilypond/lilypond/lily/axis-group-interface.cc,v
retrieving revision 1.76
diff -u -r1.76 axis-group-interface.cc
--- lily/axis-group-interface.cc	16 Mar 2006 14:39:46 -	1.76
+++ lily/axis-group-interface.cc	3 Jun 2006 02:10:06 -
@@ -8,10 +8,17 @@
 
 #include axis-group-interface.hh
 
+#include align-interface.hh
 #include pointer-group-interface.hh
 #include grob.hh
+#include grob-array.hh
 #include hara-kiri-group-spanner.hh
+#include item.hh
+#include paper-column.hh
+#include paper-score.hh
+#include system.hh
 #include warn.hh
+#include international.hh
 
 void
 

Re: Getting the height of a system.

2006-05-22 Thread Joe Neeman
On Mon, 2006-05-15 at 12:20 +0200, Han-Wen Nienhuys wrote:
 Perhaps you could even compute for each VerticalAxisGroup the range of 
 column ranks where it would disappear, and use that information add a 
 method to compute the approximate height of an alignment spanner, where 
 you explicitly call it with a (begin,end) pair of column ranks.
 
 In that case, you could get the approximate height of one broken system 
 in logarithmic time.
 
Here's a first attempt at doing this. It isn't complete or well-tested
yet. I add 4 grob properties
Y-extent-safe
Y-offset-safe
default-Y-extent-is-safe
default-Y-offset-is-safe

where Y-extent-safe and Y-offset-safe are functions that take 3
arguments, a grob, and the starting and ending column ranks.
default-Y-blah-is-safe just marks grobs where we don't need a
Y-blah-safe because the default Y-blah doesn't introduce side effects.
This is pretty much just there for NoteHead.

I've implemented Y-extent-safe for axis-group-interface,
hara-kiri-group-interface and NoteHead. I think it might be useful to do
side-position-interface also since that will take care of markups,
rehearsal marks and some other things that tend to be positioned away
from the staff. But that looks a bit harder so I haven't done it yet.

Is this similar to what you had in mind?
Index: lily/align-interface.cc
===
RCS file: /sources/lilypond/lilypond/lily/align-interface.cc,v
retrieving revision 1.97
diff -u -r1.97 align-interface.cc
--- lily/align-interface.cc	19 Feb 2006 00:14:59 -	1.97
+++ lily/align-interface.cc	22 May 2006 07:52:15 -
@@ -145,8 +145,11 @@
   align_to_fixed_distance ().
 */
 
-void
-Align_interface::align_elements_to_extents (Grob *me, Axis a)
+vectorReal
+Align_interface::get_extents_aligned_translates (Grob *me,
+		 vectorGrob* const all_grobs,
+		 Axis a,
+		 bool safe, int start, int end)
 {
   Spanner *me_spanner = dynamic_castSpanner * (me);
 
@@ -156,7 +159,7 @@
 {
   line_break_details = me_spanner-get_bound (LEFT)-get_property (line-break-system-details);
 
-  if (!me-get_system ())
+  if (!me-get_system ()  !safe)
 	me-warning (_ (vertical alignment called before line-breaking.\n
 			Only do cross-staff spanners with PianoStaff.));
 
@@ -171,10 +174,10 @@
   vectorInterval dims;
   vectorGrob* elems;
 
-  extract_grob_set (me, elements, all_grobs);
   for (vsize i = 0; i  all_grobs.size (); i++)
 {
-  Interval y = all_grobs[i]-extent (me, a);
+  Interval y = (safe  a == Y_AXIS) ? all_grobs[i]-safe_height (me, start, end)
+	: all_grobs[i]-extent (me, a);
   if (!y.is_empty ())
 	{
 	  Grob *e = dynamic_castGrob * (all_grobs[i]);
@@ -245,24 +248,31 @@
   if (translates.size ())
 {
   Real w = translates[0];
+
+  if (scm_is_number (align))
+	center_offset = total.linear_combination (scm_to_double (align));
+
   for  (vsize i = 0, j = 0; j  all_grobs.size (); j++)
 	{
 	  if (i  elems.size ()  all_grobs[j] == elems[i])
 	w = translates[i++];
-	  all_translates.push_back (w);
+	  all_translates.push_back (w - center_offset);
 	}
+}
+  return all_translates;
+}
 
-  /*
-	FIXME: uncommenting freaks out the Y-alignment of
-	line-of-score.
-  */
-  if (scm_is_number (align))
-	center_offset = total.linear_combination (scm_to_double (align));
+void
+Align_interface::align_elements_to_extents (Grob *me, Axis a)
+{
+  extract_grob_set (me, elements, all_grobs);
 
+  vectorReal translates = get_extents_aligned_translates (me, all_grobs, a, false, 0, 0);
+  if (translates.size ())
   for (vsize j = 0; j  all_grobs.size (); j++)
-	all_grobs[j]-translate_axis (all_translates[j] - center_offset, a);
-}
+	all_grobs[j]-translate_axis (translates[j], a);
 }
+
 Axis
 Align_interface::axis (Grob *me)
 {
Index: lily/axis-group-interface.cc
===
RCS file: /sources/lilypond/lilypond/lily/axis-group-interface.cc,v
retrieving revision 1.76
diff -u -r1.76 axis-group-interface.cc
--- lily/axis-group-interface.cc	16 Mar 2006 14:39:46 -	1.76
+++ lily/axis-group-interface.cc	22 May 2006 07:52:16 -
@@ -8,10 +8,14 @@
 
 #include axis-group-interface.hh
 
+#include align-interface.hh
 #include pointer-group-interface.hh
 #include grob.hh
 #include hara-kiri-group-spanner.hh
+#include item.hh
+#include paper-column.hh
 #include warn.hh
+#include international.hh
 
 void
 Axis_group_interface::add_element (Grob *me, Grob *e)
@@ -61,6 +65,41 @@
   return r;
 }
 
+Interval
+Axis_group_interface::relative_safe_height (Grob *me,
+	vectorGrob* const elts,
+	Grob *common,
+	int start, int end)
+{
+  Interval r;
+  vectorReal translates;
+
+  /* The children of an object with align-interface won't have their
+ offsets set properly because Y-offset is not safe for them. So
+ we do the translations here instead.
+  */
+
+  if (Align_interface::has_interface 

Re: Getting the height of a system.

2006-05-22 Thread Han-Wen Nienhuys

Joe Neeman schreef:
In that case, you could get the approximate height of one broken system 
in logarithmic time.



Here's a first attempt at doing this. It isn't complete or well-tested
yet. I add 4 grob properties



Y-extent-safe
Y-offset-safe
default-Y-extent-is-safe
default-Y-offset-is-safe

where Y-extent-safe and Y-offset-safe are functions that take 3
arguments, a grob, and the starting and ending column ranks.
default-Y-blah-is-safe just marks grobs where we don't need a
Y-blah-safe because the default Y-blah doesn't introduce side effects.
This is pretty much just there for NoteHead.


Can't we just get away with assuming that functions that don't have 
y-extent-safe have point dimensions?   BTW, naming would be

like

  safe-foo-bar

safe might even be renamed pure or readonly which better reflects 
the idea of the functionality.



I've implemented Y-extent-safe for axis-group-interface,
hara-kiri-group-interface and NoteHead. I think it might be useful to do
side-position-interface also since that will take care of markups,
rehearsal marks and some other things that tend to be positioned away
from the staff. But that looks a bit harder so I haven't done it yet.

Is this similar to what you had in mind?


Actually, no.

What I had in mind was only to detect when hara kiri staves are alive or 
not, and use that to make an estimate of system height (with a fixed 
system height setting). Your approach here will get more accurate 
results, but I'm a little worried that the XXX_safe functions and 
properties will spread throughout the code, which is a problem as 
they're duplicating functionality.


Does this patch already work for determining system heights, or is just 
the beginning of the work? How much more must done?


BTW, the idea of precomputing when parts of a VerticalAlignment are 
hara-kiri'd can still be used to speed up the end result, I think.


--

Han-Wen Nienhuys - [EMAIL PROTECTED] - http://www.xs4all.nl/~hanwen

LilyPond Software Design
 -- Code for Music Notation
http://www.lilypond-design.com



___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Getting the height of a system.

2006-05-22 Thread Joe Neeman
On Mon, 2006-05-22 at 10:57 +0200, Han-Wen Nienhuys wrote:
 Joe Neeman schreef:
  In that case, you could get the approximate height of one broken system 
  in logarithmic time.
 
  Here's a first attempt at doing this. It isn't complete or well-tested
  yet. I add 4 grob properties
  
  Y-extent-safe
  Y-offset-safe
  default-Y-extent-is-safe
  default-Y-offset-is-safe
  
  where Y-extent-safe and Y-offset-safe are functions that take 3
  arguments, a grob, and the starting and ending column ranks.
  default-Y-blah-is-safe just marks grobs where we don't need a
  Y-blah-safe because the default Y-blah doesn't introduce side effects.
  This is pretty much just there for NoteHead.
 
 Can't we just get away with assuming that functions that don't have 
 y-extent-safe have point dimensions?
I think so, but we would still need to have a guess for Y-offset to make
use of this.

 BTW, naming would be
 like
 
safe-foo-bar
 
 safe might even be renamed pure or readonly which better reflects 
 the idea of the functionality.
OK.

 
  I've implemented Y-extent-safe for axis-group-interface,
  hara-kiri-group-interface and NoteHead. I think it might be useful to do
  side-position-interface also since that will take care of markups,
  rehearsal marks and some other things that tend to be positioned away
  from the staff. But that looks a bit harder so I haven't done it yet.
  
  Is this similar to what you had in mind?
 
 Actually, no.
 
 What I had in mind was only to detect when hara kiri staves are alive or 
 not, and use that to make an estimate of system height (with a fixed 
 system height setting). Your approach here will get more accurate 
 results, but I'm a little worried that the XXX_safe functions and 
 properties will spread throughout the code, which is a problem as 
 they're duplicating functionality.
Yes, but I think 99% of the duplicated functionality is already in my
patch. Everything else I can think of, could be refactored like I've
done to Align_interface::align_elements_to_extents.

Most of the side-effect-causing stuff in the vertical spacing code comes
from calling extent and relative_position. Since I already have pure
versions of those, it should just be a matter of adding (bool pure, int
start, int end) to the paramaters of a few more functions and using
Grob::safe_height instead of Grob::extent when pure is true.

 
 Does this patch already work for determining system heights, or is just 
 the beginning of the work? How much more must done?
It works, but it currently only measures the height of StaffSymbol and
NoteHead. I'd like to expand it to also count things that are typically
above and below the staff. side-position-interface and
self-alignment-interface would probably be the only things left to do.
Maybe an estimate for Stem too, but that shouldn't be very important.

I want to be a little more accurate than using a fixed position for each
staff because the height of a staff can vary from piece to piece. For
example, I have a string quartet in which the 1st violin part has
systems about 20% taller than the 2nd violin because it tends to have
higher notes. The consequence in the page-breaking algorithm for
underestimating all the staff heights is that it will put too many
systems on a page and the systems will run off the bottom of the page.

OK, so the fix is easy for the user (just put system-height =
something-bigger) but I think the probability of obvious mistakes in the
default output should be _very_ low or else (1) it's inconvenient for
the user and (2) we'll get millions of duplicate bug reports and Mats
will have to patiently answer them all :)

 
 BTW, the idea of precomputing when parts of a VerticalAlignment are 
 hara-kiri'd can still be used to speed up the end result, I think.
Yes, I'll do that.


___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Getting the height of a system.

2006-05-15 Thread Han-Wen Nienhuys

Joe Neeman schreef:
I think this could be even more expensive because my page breaker looks at a 
_lot_ of different line breaking configurations. On the score I have been 
using for coverage tests (Haydn op 76, no 3, 1st violin part), the page 
breaker tests more than 4000 different line breaking configurations so this 
is already much more expensive than doing it for 50-60 copies of the score.


ok


Also, it's not completely possible to compute the height of an isolated
system: some grobs (notably spanners like slur) look at the next system
to decide how to format across line breaks.


Would it be acceptable to skip those cases? This would be a good point to 


Yes.

mention that I don't really need the exact height of the system -- just an 
approximation. The current approximation I am using (setting a score-wide 
system-height) is _very_ crude but it works pretty well as long as there are 
no RemoveEmptyStaffContexts or very high notes.


I think that actually the RemoveEmptyStaffContexts are the difficult 
parts, the high notes would be an exception.




Secondly, although it will be nicely portable, it also sounds like a lot
of work. Isn't it a lot easier to simply do a fork() and let the OS
clean up after us? Perhaps if the vertical spacing is completely
working, we can consider doing the full-blown copy and restore. Also,
for large scores, fork() is an interesting option, as we could get some
benefit from using SMP.


But then the OS would have to deal with copying the data and it can only do 
that in page-sized chunks. So wouldn't this just increase the amount of stuff 
that gets copied?


Yes, but it's a much easier to be certain that it is correct than 
writing copying and cleanup stuff in C++.


There is actually another possibility that I've only just thought of so it's 
pretty half-baked:

Add an approximate-Y-extent to each grob that
1) leaves the grob constant (in particular no caching)
2) ignores anything in the object_alist_ that doesn't have a system.

Then we could even get away with not doing any break-substitutions (until it's 
time to typeset things, of course) with something like:

Real System::guess_line_height (Column_x_positions col)
{
set_bound (LEFT, col.cols_[0]);
set_bound (RIGHT, col.cols_.back ());
for (vsize i = 0; i  col.cols_.size (); i++)
{
// translate axis (as in System::break_into_pieces)
col.cols_[i].system_ = this;
}
set_loose_columns (this, col);
SCM h = this-get_property (approximate-Y-extent);
for (vsize i = 0; i  col.cols_.size (); i++)
{
// translate the axis back
col.cols_.system_ = 0;
}
return scm_to_double (h);
}

That is, we can pretend we're working on the original system and get away with 
it because approximate-Y-extent will be guaranteed not to leave any 
side-effects. Condition (2) means that we can get away with doing it a system 
at a time. A spanner that crosses a line break will realise that it is 
crossing the line break and will try to provide a sensible guess.


I think that's a sensible stop gap solution, but I have a feeling it 
will be a lot of work. Perhaps it's better to approach from the other 
side, and only explicitly do this for alignment spanners.


Perhaps you could even compute for each VerticalAxisGroup the range of 
column ranks where it would disappear, and use that information add a 
method to compute the approximate height of an alignment spanner, where 
you explicitly call it with a (begin,end) pair of column ranks.


In that case, you could get the approximate height of one broken system 
in logarithmic time.


--

Han-Wen Nienhuys - [EMAIL PROTECTED] - http://www.xs4all.nl/~hanwen

LilyPond Software Design
 -- Code for Music Notation
http://www.lilypond-design.com



___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Getting the height of a system.

2006-05-15 Thread Joe Neeman
On Mon, 2006-05-15 at 12:20 +0200, Han-Wen Nienhuys wrote:
 Joe Neeman schreef:
  There is actually another possibility that I've only just thought of so 
  it's 
  pretty half-baked:
  Add an approximate-Y-extent to each grob that
  1) leaves the grob constant (in particular no caching)
  2) ignores anything in the object_alist_ that doesn't have a system.
  
  Then we could even get away with not doing any break-substitutions (until 
  it's 
  time to typeset things, of course) with something like:
  Real System::guess_line_height (Column_x_positions col)
  {
  set_bound (LEFT, col.cols_[0]);
  set_bound (RIGHT, col.cols_.back ());
  for (vsize i = 0; i  col.cols_.size (); i++)
  {
  // translate axis (as in System::break_into_pieces)
  col.cols_[i].system_ = this;
  }
  set_loose_columns (this, col);
  SCM h = this-get_property (approximate-Y-extent);
  for (vsize i = 0; i  col.cols_.size (); i++)
  {
  // translate the axis back
  col.cols_.system_ = 0;
  }
  return scm_to_double (h);
  }
  
  That is, we can pretend we're working on the original system and get away 
  with 
  it because approximate-Y-extent will be guaranteed not to leave any 
  side-effects. Condition (2) means that we can get away with doing it a 
  system 
  at a time. A spanner that crosses a line break will realise that it is 
  crossing the line break and will try to provide a sensible guess.
 
 I think that's a sensible stop gap solution, but I have a feeling it 
 will be a lot of work. Perhaps it's better to approach from the other 
 side, and only explicitly do this for alignment spanners.
 
 Perhaps you could even compute for each VerticalAxisGroup the range of 
 column ranks where it would disappear, and use that information add a 
 method to compute the approximate height of an alignment spanner, where 
 you explicitly call it with a (begin,end) pair of column ranks.
 
 In that case, you could get the approximate height of one broken system 
 in logarithmic time.

That sounds encouraging! I don't fully understand how alignment spanners
work since I haven't had much to do with that part of the code (yet).
But this looks like something I can go on with -- I'll be back if/when
I've made something useful out of it.


___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Getting the height of a system.

2006-05-14 Thread Han-Wen Nienhuys

Joe Neeman schreef:
We discussed this a bit a long time ago but I'm getting close to actually 
implementing something so I thought I'd bring it up again.


Getting the Y-extent of a system is potentially destructive, causing all sorts 
of non-undoable caching and possibly suiciding of grobs. So I need to do make 
a copy of the system before I can get its Y-extent.


The problem is that there are a large number of possible lines in a score. To 
copy a system, I need to do a full grob substitution for every grob in that 
system. If each bar could be in up to N possible lines, I need to do N full 
copies of the entire score and N full grob substitutions in the 
object_alist_. If we can fit up to K bars to a line then N is approximately 
K(K-1)/2. In the scores I typically work with, N would be around 50-60 so 
this is getting pretty expensive.


It's much worse than that, because the cost of the substitution is 
actually proportional to the number grobs in the long System, i.e. the 
length of the entire score.  It would be much much better if you could 
make your algorithm compute the system heights of a complete line 
breaking configuration.


Also, it's not completely possible to compute the height of an isolated 
system: some grobs (notably spanners like slur) look at the next system 
to decide how to format across line breaks.


So I propose the following instead. I don't know a great deal (yet) about the 
C++ internals of grobs so I'd appreciate knowing if this is unworkable before 
I spend lots of time trying to implement it.


1) add a virtual Grob *save () and virtual void restore (Grob*) function to 
every C++ Grob subclass. save() would be a bit like clone except that it 
copies the object_alist_ and, for example, broken_intos_ in the case of a 
Spanner.

Grob *copy = me-save ();
// make some changes to me
me-restore (copy);
and you end up with the same grob you started with.

2) save every grob in the score

3) for each possible system, using the original grobs,
- work out the Y-extent
- restore () every grob in that system

The advantage is that we avoid fiddling around with the object_alist_ because 
this clone is never used -- it exists only to save the state of the score 
before we mess it up with calling Y-extent. We also only have to make one 
copy of the system and restore it N times instead of making N copies.


Sounds like a possiblity, but have you also considered break alignments? 
It's not only the object_alist_  (and property_alist_, as that too will 
change), but also other pointers like original_.


Secondly, although it will be nicely portable, it also sounds like a lot 
of work. Isn't it a lot easier to simply do a fork() and let the OS 
clean up after us? Perhaps if the vertical spacing is completely 
working, we can consider doing the full-blown copy and restore. Also, 
for large scores, fork() is an interesting option, as we could get some 
benefit from using SMP.


--

Han-Wen Nienhuys - [EMAIL PROTECTED] - http://www.xs4all.nl/~hanwen

LilyPond Software Design
 -- Code for Music Notation
http://www.lilypond-design.com



___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Getting the height of a system.

2006-05-14 Thread Han-Wen Nienhuys

Han-Wen Nienhuys schreef:


3) for each possible system, using the original grobs,
- work out the Y-extent
- restore () every grob in that system

The advantage is that we avoid fiddling around with the object_alist_ 
because this clone is never used -- it exists only to save the state 
of the score before we mess it up with calling Y-extent. We also only 
have to make one copy of the system and restore it N times instead of 
making N copies.


I don't think that this will really help. Inside the grobs, the 
object_alist_ will contain grob_arrays, which are considered 'private 
data' to each grob, and hence need to be copied completely before each 
new System formatting step. This is expensive, as the length of the 
grob_arrays is proportional to the entire score.




--

Han-Wen Nienhuys - [EMAIL PROTECTED] - http://www.xs4all.nl/~hanwen

LilyPond Software Design
 -- Code for Music Notation
http://www.lilypond-design.com



___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Getting the height of a system.

2006-05-14 Thread Joe Neeman
On Sun, 14 May 2006 20:40, Han-Wen Nienhuys wrote:
 Joe Neeman schreef:
  We discussed this a bit a long time ago but I'm getting close to actually
  implementing something so I thought I'd bring it up again.
 
  Getting the Y-extent of a system is potentially destructive, causing all
  sorts of non-undoable caching and possibly suiciding of grobs. So I need
  to do make a copy of the system before I can get its Y-extent.
 
  The problem is that there are a large number of possible lines in a
  score. To copy a system, I need to do a full grob substitution for every
  grob in that system. If each bar could be in up to N possible lines, I
  need to do N full copies of the entire score and N full grob
  substitutions in the
  object_alist_. If we can fit up to K bars to a line then N is
  approximately K(K-1)/2. In the scores I typically work with, N would be
  around 50-60 so this is getting pretty expensive.

 It's much worse than that, because the cost of the substitution is
 actually proportional to the number grobs in the long System, i.e. the
 length of the entire score.  It would be much much better if you could
 make your algorithm compute the system heights of a complete line
 breaking configuration.

I think this could be even more expensive because my page breaker looks at a 
_lot_ of different line breaking configurations. On the score I have been 
using for coverage tests (Haydn op 76, no 3, 1st violin part), the page 
breaker tests more than 4000 different line breaking configurations so this 
is already much more expensive than doing it for 50-60 copies of the score.

 Also, it's not completely possible to compute the height of an isolated
 system: some grobs (notably spanners like slur) look at the next system
 to decide how to format across line breaks.

Would it be acceptable to skip those cases? This would be a good point to 
mention that I don't really need the exact height of the system -- just an 
approximation. The current approximation I am using (setting a score-wide 
system-height) is _very_ crude but it works pretty well as long as there are 
no RemoveEmptyStaffContexts or very high notes.


  So I propose the following instead. I don't know a great deal (yet) about
  the C++ internals of grobs so I'd appreciate knowing if this is
  unworkable before I spend lots of time trying to implement it.
 
  1) add a virtual Grob *save () and virtual void restore (Grob*) function
  to every C++ Grob subclass. save() would be a bit like clone except that
  it copies the object_alist_ and, for example, broken_intos_ in the case
  of a Spanner.
  Grob *copy = me-save ();
  // make some changes to me
  me-restore (copy);
  and you end up with the same grob you started with.
 
  2) save every grob in the score
 
  3) for each possible system, using the original grobs,
  - work out the Y-extent
  - restore () every grob in that system
 
  The advantage is that we avoid fiddling around with the object_alist_
  because this clone is never used -- it exists only to save the state of
  the score before we mess it up with calling Y-extent. We also only have
  to make one copy of the system and restore it N times instead of making N
  copies.

 Sounds like a possiblity, but have you also considered break alignments?
 It's not only the object_alist_  (and property_alist_, as that too will
 change), but also other pointers like original_.

I hadn't, but it's just a matter of copying a few more bits of data, right?


 Secondly, although it will be nicely portable, it also sounds like a lot
 of work. Isn't it a lot easier to simply do a fork() and let the OS
 clean up after us? Perhaps if the vertical spacing is completely
 working, we can consider doing the full-blown copy and restore. Also,
 for large scores, fork() is an interesting option, as we could get some
 benefit from using SMP.

But then the OS would have to deal with copying the data and it can only do 
that in page-sized chunks. So wouldn't this just increase the amount of stuff 
that gets copied?

Getting a bit OT, the gomp project was recently checked in for GCC 4.2 
[http://gcc.gnu.org/wiki/GCC 4.2 Projects]. If you want to introduce 
parallelism, it might be a worthwhile thing to wait for since it is portable 
and _much_ easier to use than either fork() or pthreads.


There is actually another possibility that I've only just thought of so it's 
pretty half-baked:
Add an approximate-Y-extent to each grob that
1) leaves the grob constant (in particular no caching)
2) ignores anything in the object_alist_ that doesn't have a system.

Then we could even get away with not doing any break-substitutions (until it's 
time to typeset things, of course) with something like:
Real System::guess_line_height (Column_x_positions col)
{
set_bound (LEFT, col.cols_[0]);
set_bound (RIGHT, col.cols_.back ());
for (vsize i = 0; i  col.cols_.size (); i++)
{
// translate axis (as in 

Getting the height of a system.

2006-05-13 Thread Joe Neeman
We discussed this a bit a long time ago but I'm getting close to actually 
implementing something so I thought I'd bring it up again.

Getting the Y-extent of a system is potentially destructive, causing all sorts 
of non-undoable caching and possibly suiciding of grobs. So I need to do make 
a copy of the system before I can get its Y-extent.

The problem is that there are a large number of possible lines in a score. To 
copy a system, I need to do a full grob substitution for every grob in that 
system. If each bar could be in up to N possible lines, I need to do N full 
copies of the entire score and N full grob substitutions in the 
object_alist_. If we can fit up to K bars to a line then N is approximately 
K(K-1)/2. In the scores I typically work with, N would be around 50-60 so 
this is getting pretty expensive.

So I propose the following instead. I don't know a great deal (yet) about the 
C++ internals of grobs so I'd appreciate knowing if this is unworkable before 
I spend lots of time trying to implement it.

1) add a virtual Grob *save () and virtual void restore (Grob*) function to 
every C++ Grob subclass. save() would be a bit like clone except that it 
copies the object_alist_ and, for example, broken_intos_ in the case of a 
Spanner.
Grob *copy = me-save ();
// make some changes to me
me-restore (copy);
and you end up with the same grob you started with.

2) save every grob in the score

3) for each possible system, using the original grobs,
- work out the Y-extent
- restore () every grob in that system

The advantage is that we avoid fiddling around with the object_alist_ because 
this clone is never used -- it exists only to save the state of the score 
before we mess it up with calling Y-extent. We also only have to make one 
copy of the system and restore it N times instead of making N copies.

Is this feasible?


___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel